from collections import OrderedDict

from django.test import TestCase

from model_mommy import mommy

from abscrete.models import (AbscreteMeta, AbscreteType, AbscreteTree)
import abscrete.tests.models as tm

for m in [tm.PlainRoot, tm.PlainLeaf1, tm.PlainLeaf2, tm.PlainLeaf3,
          tm.RootWithOneNode, tm.IntermediateNode,
          tm.LeafWithIntermediate1, tm.LeafWithIntermediate2,
          tm.LeafWithIntermediate3, tm.LeafWithIntermediate4]:
    m._abscrete.tree.prune(m)

class AbscreteTestCase(TestCase):
    #: A list of the root models for the test case
    roots = None
    #: The part of the tree that is immediately below the root models, in the
    # form of a dictionnary of OrderedDict()
    tree = None
    #: A dictionary of the leaves of the test case, with the leaf class as key
    # and the branch leading up to the root as value
    leaves = None
    #: A dictionary of the nodes of the test case, with the node class as key
    # and the branch leading up to the root as value
    nodes = None

# Definition of all the test cases data

class OnePlainRoot(AbscreteTestCase):
    """
    In those tests, there is a single root which has a couple of leafs. This is
    the simplest setup.
    """
    @classmethod
    def setUpTestData(cls):
        cls.roots = [tm.PlainRoot]
        cls.tree = {
            tm.PlainRoot: OrderedDict(
                [(tm.PlainLeaf1, OrderedDict()),
                 (tm.PlainLeaf2, OrderedDict()),
                 (tm.PlainLeaf3, OrderedDict())]
            )
        }
        cls.leaves = {
            tm.PlainLeaf1: [tm.PlainRoot],
            tm.PlainLeaf2: [tm.PlainRoot],
            tm.PlainLeaf3: [tm.PlainRoot],
        }
        cls.nodes = {}

class SeveralPlainRoots(AbscreteTestCase):
    """
    In those tests, there are several roots, each of them having a couple of
    leaves directly below them
    """
    @classmethod
    def setUpTestData(cls):
        cls.roots = [tm.SeveralPlainRoot1,
                     tm.SeveralPlainRoot2,
                     tm.SeveralPlainRoot3]
        cls.tree = {
            tm.SeveralPlainRoot1: OrderedDict(
                [(tm.SeveralPlainLeaf11, OrderedDict()),
                 (tm.SeveralPlainLeaf12, OrderedDict())]
            ),
            tm.SeveralPlainRoot2: OrderedDict(
                [(tm.SeveralPlainLeaf21, OrderedDict()),
                 (tm.SeveralPlainLeaf22, OrderedDict())]
            ),
            tm.SeveralPlainRoot3: OrderedDict(
                [(tm.SeveralPlainLeaf31, OrderedDict()),
                 (tm.SeveralPlainLeaf32, OrderedDict())]
            )
        }
        cls.leaves = {
            tm.SeveralPlainLeaf11: [tm.SeveralPlainRoot1],
            tm.SeveralPlainLeaf12: [tm.SeveralPlainRoot1],
            tm.SeveralPlainLeaf21: [tm.SeveralPlainRoot2],
            tm.SeveralPlainLeaf22: [tm.SeveralPlainRoot2],
            tm.SeveralPlainLeaf31: [tm.SeveralPlainRoot3],
            tm.SeveralPlainLeaf32: [tm.SeveralPlainRoot3]
        }
        cls.nodes = {}

class OneIntermediateNode(AbscreteTestCase):
    """
    Those tests feature an intermediate node, which has several leafs below it.
    """
    @classmethod
    def setUpTestData(cls):
        cls.roots = [tm.RootWithOneNode]
        cls.tree = {
            tm.RootWithOneNode: OrderedDict(
                [(tm.IntermediateNode, OrderedDict(
                    [(tm.LeafWithIntermediate1, OrderedDict()),
                     (tm.LeafWithIntermediate2, OrderedDict()),
                     (tm.LeafWithIntermediate3, OrderedDict()),
                     (tm.LeafWithIntermediate4, OrderedDict())]
                ))]
            )
        }
        cls.leaves = {
            tm.LeafWithIntermediate1: [tm.IntermediateNode, tm.RootWithOneNode],
            tm.LeafWithIntermediate2: [tm.IntermediateNode, tm.RootWithOneNode],
            tm.LeafWithIntermediate3: [tm.IntermediateNode, tm.RootWithOneNode],
            tm.LeafWithIntermediate4: [tm.IntermediateNode, tm.RootWithOneNode]
        }
        cls.nodes = {
            tm.IntermediateNode: [tm.RootWithOneNode]
        }

class SeveralIntermediateNodes(AbscreteTestCase):
    """
    Those tests have a cascade of intermediate nodes, with a single leaf at the
    end.
    """
    @classmethod
    def setUpTestData(cls):
        cls.roots = [tm.RootWithSeveralNodes]
        cls.tree = {
            tm.RootWithSeveralNodes: OrderedDict(
                [(tm.IntermediateNode1, OrderedDict(
                    [(tm.IntermediateNode2, OrderedDict(
                        [(tm.IntermediateNode3, OrderedDict(
                            [(tm.LeafWithSeveralIntermediate, OrderedDict())]
                        ))]
                    ))]
                ))]
            )
        }
        cls.leaves = {
            tm.LeafWithSeveralIntermediate: [tm.IntermediateNode3,
                                             tm.IntermediateNode2,
                                             tm.IntermediateNode1,
                                             tm.RootWithSeveralNodes]
        }
        cls.nodes = {
            tm.IntermediateNode3: [tm.IntermediateNode2,
                                   tm.IntermediateNode1,
                                   tm.RootWithSeveralNodes],
            tm.IntermediateNode2: [tm.IntermediateNode1,
                                   tm.RootWithSeveralNodes],
            tm.IntermediateNode1: [tm.RootWithSeveralNodes],
        }

class RandomTree(AbscreteTestCase):
    """
    This test has no particular logic but mixes all kinds of tree structures to
    see if everything goes well.
    """
    @classmethod
    def setUpTestData(cls):
        cls.roots = [tm.Root1,
                     tm.Root2]
        cls.tree = {
            tm.Root1: OrderedDict(
                [(tm.Leaf11, OrderedDict()),
                 (tm.Node11, OrderedDict(
                     [(tm.Leaf111, OrderedDict()),
                      (tm.Leaf112, OrderedDict())]
                 ))]
            ),
            tm.Root2: OrderedDict(
                [(tm.Node21, OrderedDict(
                    [(tm.Node211, OrderedDict(
                            [(tm.Leaf2111, OrderedDict())]
                    )),
                     (tm.Leaf211, OrderedDict())]
                ))]
            )
        }
        cls.leaves = {
            tm.Leaf11: [tm.Root1],
            tm.Leaf111: [tm.Node11, tm.Root1],
            tm.Leaf112: [tm.Node11, tm.Root1],
            tm.Leaf2111: [tm.Node211, tm.Node21, tm.Root2],
            tm.Leaf211: [tm.Node21, tm.Root2]
        }
        cls.nodes = {
            tm.Node11: [tm.Root1],
            tm.Node21: [tm.Root2],
            tm.Node211: [tm.Node21, tm.Root2]
        }

# Definition of the actual test functions

class AbscreteMetaTest:
    def _test_common_attributes(self, model):
        self.assertTrue(hasattr(model, '_abscrete'))

        abscrete = model._abscrete
        self.assertTrue(isinstance(abscrete, AbscreteMeta))
        self.assertIsNotNone(abscrete.type)
        self.assertIsNotNone(abscrete.tree)
        self.assertTrue(isinstance(abscrete.tree, AbscreteTree))

    def _test_non_root_attributes(self, abscrete, branch):
        self.assertEqual(abscrete.branch, branch)
        self.assertEqual(abscrete.branch.parent, branch[0] if branch else None)
        self.assertEqual(abscrete.branch.root, branch[-1] if branch else None)

        for r in self.roots:
            self.assertEqual(abscrete.tree[r], self.tree[r])

    def test_roots(self):
        for r in self.roots:
            self._test_common_attributes(r)

            abscrete = r._abscrete
            self.assertEqual(abscrete.type, AbscreteType.ROOT)
            self.assertIsNone(abscrete.branch.root)
            self.assertEqual(abscrete.branch, [])

    def test_nodes(self):
        for n, branch in self.nodes.items():
            self._test_common_attributes(n)

            abscrete = n._abscrete
            self.assertEqual(abscrete.type, AbscreteType.NODE)
            self._test_non_root_attributes(abscrete, branch)

    def test_leaves(self):
        for l, branch in self.leaves.items():
            self._test_common_attributes(l)

            abscrete = l._abscrete
            self.assertEqual(abscrete.type, AbscreteType.LEAF)
            self._test_non_root_attributes(abscrete, branch)

class AbscreteModelTest(object):
    @classmethod
    def setUpTestData(cls):
        super(AbscreteModelTest, cls).setUpTestData()
        cls.leaf_instances = [
            (mommy.make(kls), branch) for kls, branch in cls.leaves.items()
        ]

    def test_abscrete_branch(self):
        for l, branch in self.leaf_instances:
            root = branch[-1]
            self.assertTrue(
                hasattr(l, 'abscrete_field_name'),
                'leaves should have a abscrete_field_name attribute'
            )
            self.assertEqual(
                l.abscrete_field_name,
                'abscrete_type_%s' % root.__name__.lower()
            )
            self.assertTrue(
                hasattr(l, 'abscrete_branch'),
                'leaves should have a abscrete_branch attribute'
            )
            self.assertEqual(
                l.abscrete_branch,
                '.'.join(
                    [n.__name__.lower() for n in reversed(l._abscrete.branch)]
                    + [l.__class__.__name__.lower()]
                )
            )

    def test_abscrete_instance(self):
        for l, branch in self.leaf_instances:
            root = branch[-1]
            root_instance = getattr(l, '%s_ptr' % root.__name__.lower())

            self.assertTrue(isinstance(root_instance, branch[-1]))
            self.assertEqual(root_instance.abscrete_instance, l)

class AbstractQuerySetTest(object):
    @classmethod
    def setUpTestData(cls):
        super(AbstractQuerySetTest, cls).setUpTestData()
        cls.leaves_instances = [
            (kls, branch[-1], mommy.make(kls, _quantity=5))
            for kls, branch in cls.leaves.items()
        ]

    def _test_root_queryset(self, root, leaves_list):
        qs = root.objects.all()
        self.assertSetEqual(set(leaves_list), set(qs))
        self.assertSequenceEqual(leaves_list, qs)

    def _test_leaf_queryset(self, leaf, leaves_list):
        qs = leaf.objects.all()
        self.assertSetEqual(set(qs), set(leaves_list))
        self.assertSequenceEqual(leaves_list, qs)

    def test_root_queryset(self):
        leaves_by_root = {
            r: [l for _, l_root, list in self.leaves_instances
                if l_root == r for l in list]
            for r in self.roots
        }
        for root, leaves_list in leaves_by_root.items():
            self._test_root_queryset(root, leaves_list)

    def test_leaves_queryset(self):
        for kls, _, list in self.leaves_instances:
            self._test_leaf_queryset(kls, list)

# Concrete implementation of the tests which combine some standard data set-up
# and the actual test functions

class AbscreteMetaTestPlain(AbscreteMetaTest, OnePlainRoot):
    pass
class AbscreteMetaSeveralPlainTest(AbscreteMetaTest, SeveralPlainRoots):
    pass
class AbscreteMetaOneIntermediateNodeTest(AbscreteMetaTest, OneIntermediateNode):
    pass
class AbscreteMetaSeveralIntermediateNodesTest(AbscreteMetaTest, SeveralIntermediateNodes):
    pass
class AbscreteMetaRandomTreeTest(AbscreteMetaTest, RandomTree):
    pass

class AbscreteModelTestPlain(AbscreteModelTest, OnePlainRoot):
    pass
class AbscreteModelTestSeveralPlain(AbscreteModelTest, SeveralPlainRoots):
    pass
class AbscreteModelTestOneIntermediateNode(AbscreteModelTest, OneIntermediateNode):
    pass
class AbscreteModelTestSeveralIntermediateNodes(AbscreteModelTest, SeveralIntermediateNodes):
    pass
class AbscreteModelTestRandomTree(AbscreteModelTest, RandomTree):
    pass

class AbscreteQuerySetTestPlain(AbstractQuerySetTest, OnePlainRoot):
    pass
class AbscreteQuerySetTestSeveralPlain(AbstractQuerySetTest, SeveralPlainRoots):
    pass
class AbscreteQuerySetTestOneIntermediateNode(AbstractQuerySetTest, OneIntermediateNode):
    pass
class AbscreteQuerySetTestSeveralIntermediateNodes(AbstractQuerySetTest, SeveralIntermediateNodes):
    pass
class AbscreteQuerySetTestRandomTree(AbstractQuerySetTest, RandomTree):
    pass

class OneToOneRelationTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.root1_instances = {
            tm.O2ORelationLeaf11: mommy.make(tm.O2ORelationLeaf11, _quantity=2),
            tm.O2ORelationLeaf12: mommy.make(tm.O2ORelationLeaf12, _quantity=2),
        }
        cls.root2_instances = {
            tm.O2ORelationLeaf21: {
                tm.O2ORelationLeaf11: mommy.make(
                    tm.O2ORelationLeaf21,
                    o2orelationroot1=cls.root1_instances[tm.O2ORelationLeaf11][0]
                ),
                tm.O2ORelationLeaf12: mommy.make(
                    tm.O2ORelationLeaf21,
                    o2orelationroot1=cls.root1_instances[tm.O2ORelationLeaf12][0]
                ),
            },
            tm.O2ORelationLeaf22: {
                tm.O2ORelationLeaf11: mommy.make(
                    tm.O2ORelationLeaf22,
                    o2orelationroot1=cls.root1_instances[tm.O2ORelationLeaf11][1]
                ),
                tm.O2ORelationLeaf12: mommy.make(
                    tm.O2ORelationLeaf22,
                    o2orelationroot1=cls.root1_instances[tm.O2ORelationLeaf12][1]
                ),
            },
        }

    def test_subclassing(self):
        for kls, instances in self.root2_instances.items():
            for related_class, i in instances.items():
                self.assertTrue(isinstance(i.o2orelationroot1, related_class))

        for kls, list in self.root1_instances.items():
            for i in list:
                related_to = i.o2orelationroot2
                self.assertNotEqual(related_to.__class__, tm.O2ORelationRoot2)
                self.assertIn(related_to.__class__,
                              [tm.O2ORelationLeaf21, tm.O2ORelationLeaf22])

class ForeignRelationTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.root1_instances = {
            tm.ForeignRelationLeaf11: mommy.make(tm.ForeignRelationLeaf11),
            tm.ForeignRelationLeaf12: mommy.make(tm.ForeignRelationLeaf12),
        }
        cls.root2_instances = {
            tm.ForeignRelationLeaf21: {
                tm.ForeignRelationLeaf11: mommy.make(
                    tm.ForeignRelationLeaf21,
                    foreignrelationroot1=cls.root1_instances[tm.ForeignRelationLeaf11]
                ),
                tm.ForeignRelationLeaf12: mommy.make(
                    tm.ForeignRelationLeaf21,
                    foreignrelationroot1=cls.root1_instances[tm.ForeignRelationLeaf12]
                ),
            },
            tm.ForeignRelationLeaf22: {
                tm.ForeignRelationLeaf11: mommy.make(
                    tm.ForeignRelationLeaf22,
                    foreignrelationroot1=cls.root1_instances[tm.ForeignRelationLeaf11]
                ),
                tm.ForeignRelationLeaf12: mommy.make(
                    tm.ForeignRelationLeaf22,
                    foreignrelationroot1=cls.root1_instances[tm.ForeignRelationLeaf12]
                ),
            },
        }

    def test_subclassing(self):
        for kls, instances in self.root2_instances.items():
            for related_class, i in instances.items():
                self.assertTrue(isinstance(i.foreignrelationroot1, related_class))

        for kls, i in self.root1_instances.items():
            for related_to in i.foreignrelationroot2_set.all():
                self.assertNotEqual(related_to.__class__, tm.ForeignRelationRoot2)
                self.assertIn(related_to.__class__,
                              [tm.ForeignRelationLeaf21, tm.ForeignRelationLeaf22])

class M2MRelationTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.root1_instances = {
            tm.M2MRelationLeaf11: mommy.make(tm.M2MRelationLeaf11),
            tm.M2MRelationLeaf12: mommy.make(tm.M2MRelationLeaf12),
        }
        cls.root2_instances = {
            tm.M2MRelationLeaf21: mommy.make(tm.M2MRelationLeaf21),
            tm.M2MRelationLeaf22: mommy.make(tm.M2MRelationLeaf22),
        }
        cls.root2_instances[tm.M2MRelationLeaf21].m2mrelationroot1_set.add(
            cls.root1_instances[tm.M2MRelationLeaf11]
        )
        cls.root2_instances[tm.M2MRelationLeaf21].m2mrelationroot1_set.add(
            cls.root1_instances[tm.M2MRelationLeaf12]
        )
        cls.root2_instances[tm.M2MRelationLeaf22].m2mrelationroot1_set.add(
            cls.root1_instances[tm.M2MRelationLeaf11]
        )
        cls.root2_instances[tm.M2MRelationLeaf22].m2mrelationroot1_set.add(
            cls.root1_instances[tm.M2MRelationLeaf12]
        )

    def test_subclassing(self):
        for kls, i in self.root1_instances.items():
            for related in i.m2mrelationroot2_set.all():
                self.assertNotEqual(related.__class__, tm.M2MRelationRoot2)
                self.assertIn(related.__class__,
                              [tm.M2MRelationLeaf21, tm.M2MRelationLeaf22])

        for kls, i in self.root2_instances.items():
            for related in i.m2mrelationroot1_set.all():
                self.assertNotEqual(related.__class__, tm.M2MRelationRoot1)
                self.assertIn(related.__class__,
                              [tm.M2MRelationLeaf11, tm.M2MRelationLeaf12])


from __future__ import annotations

import random

from typing import TYPE_CHECKING, Type

from .expansion import Expansion
from ..cards import cards, cornucopia_cards
from ..grammar import s, it_or_them
from ..supply import FiniteSupplyStack

if TYPE_CHECKING:
    from ..cards.cards import Card

class CornucopiaExpansion(Expansion):
    name = 'Cornucopia'

    def __init__(self, game, bane_card_class: Type[Card] | None = None):
        super().__init__(game)
        self.bane_card_class = bane_card_class
        self.prizes = [prize() for prize in cornucopia_cards.PRIZES]

    @property
    def basic_card_piles(self):
        return []

    @property
    def kingdom_card_classes(self):
        return cornucopia_cards.KINGDOM_CARDS

    def add_additional_kingdom_cards(self):
        # If the Young Witch is in the Supply, it adds an extra Kingdom card pile costing 2 $ or 3 $ to the Supply. Cards from that pile are Bane cards.
        if cornucopia_cards.YoungWitch in self.supply.card_stacks:
            # If a Bane card is specified (e.g. by a recommended set), use that one
            if self.bane_card_class:
                bane_card_class = self.bane_card_class
            # Otherwise, randomly choose a card class costing 2 $ or 3 $ to be the Bane card
            else:
                possible_bane_card_classes = [card_class for card_class in self.supply.possible_kingdom_card_classes if card_class not in self.supply.card_stacks and card_class._cost in [2, 3]]
                # If there are no cards costing 2 $ or 3 $, then remove one from the Supply, replace it with something else, and use it as a Bane card
                if not possible_bane_card_classes:
                    card_classes_costing_2_or_3 = [card_class for card_class in self.supply.card_stacks if card_class._cost in [2, 3]]
                    bane_card_class = random.choice(card_classes_costing_2_or_3)
                    self.supply.card_stacks.pop(bane_card_class)
                    replacement_card_class = random.choice(self.supply.possible_kingdom_card_classes)
                    self.supply.card_stacks[replacement_card_class] = FiniteSupplyStack(replacement_card_class, 10)
                else:
                    bane_card_class = random.choice(possible_bane_card_classes)
            self.game.broadcast(f"The Young Witch is in play this game. {s(10, bane_card_class.name, print_number=False)} are Bane cards.")
            # Add the Bane card class to the Supply and modify its example card
            self.supply.card_stacks[bane_card_class] = FiniteSupplyStack(bane_card_class, 10)
            self.supply.card_stacks[bane_card_class].example.types += [cards.CardType.BANE]
        # If the Tournament is in the Supply, it adds Prizes
        if cornucopia_cards.Tournament in self.supply.card_stacks:
            self.game.broadcast("The Tournament is in play this game. Prizes are available.")

    def additional_setup(self):
        pass

    def heartbeat(self):
        # Display prizes
        if cornucopia_cards.Tournament in self.game.supply.card_stacks:
            self.game.socketio.emit(
                "prizes",
                {
                    "cards": [card.json for card in self.prizes]
                },
                room=self.game.room,
            )

    def order_treasures(self, player, treasures):
        # If any Horns of Plenty are in the played treasures, allow the player to play them last
        if any(isinstance(treasure, cornucopia_cards.HornOfPlenty) for treasure in treasures):
            # Find all played Horns of Plenty
            horns_of_plenty = [treasure for treasure in treasures if isinstance(treasure, cornucopia_cards.HornOfPlenty)]
            # Ask the player if they want to play them last
            prompt = f"You played {s(len(horns_of_plenty), cornucopia_cards.HornOfPlenty)}. Would you like to play {it_or_them(len(horns_of_plenty))} last to maximize the number of differently named cards played this turn?"
            if player.interactions.choose_yes_or_no(prompt):
                # Remove the Horns of Plenty from the list of played treasures
                treasures = [treasure for treasure in treasures if not isinstance(treasure, cornucopia_cards.HornOfPlenty)]
                # Add the Horns of Plenty to the end of the list of played treasures
                treasures.extend(horns_of_plenty)
        return treasures

    @property
    def game_end_conditions(self):
        return []

    def scoring(self, player):
        return 0


# squareroot.py
# This program takes a positive floating-point number as input and return the approximate square root of a number using Newtons method
# Author: Miriam Heinlein

# User Input - positive number with decimal point using the float format
n = float(input ("Please enter a positive number: "))

#sqrt function to cacluate the approx. square root of n (user input (positive number))
def newtonSqrt(n):

    # Setting variables
    approx = 0.5 * n # for example n = 10 --> 5
    root = 0.5 * (approx+(n/approx)) # root with n=10 is 3.5

    while root !=approx: # Executes the while loop until the approximation is equal to the root

        approx = root # every time approx will be changed to root, in example to 3.5 until finally the values align --> return
        root =  (approx +(n/approx))/2  # 0.5 * or /2 is the same
    return approx

# Output returning approx. square root with one decimal digit
print ("The square root of", n, "is approx. {:.1f}".format(float(newtonSqrt(n))))


'''
Profile test execution using cProfile.
Config option ``sort`` can be used to change how profiling information
is presented.
'''
__all__ = ('Profiler',)

import logging
import cProfile
import pstats

import nose2

log = logging.getLogger('.'.join(('nose2', 'plugins', __package__)))

class Profiler(nose2.events.Plugin):

    '''Profile the test run using cProfile'''

    configSection = 'profiler'
    commandLineSwitch = ('P', 'profile', 'Run test under cprofile')

    def __init__(self):
        self.sort = self.config.as_str('sort', 'cumulative')
        self.prof = None

    def startTestRun(self, event):
        '''Setup profiler'''
        self.prof = cProfile.Profile()
        event.executeTests = self.prof.runcall

    def beforeSummaryReport(self, event):
        '''Output profiling results'''
        self.prof.disable()
        stats = pstats.Stats(self.prof, stream=event.stream).sort_stats(
            self.sort)
        event.stream.writeln(nose2.util.ln('Profiling results'))
        stats.print_stats()


from flask import Flask, render_template, request, redirect, send_from_directory, session, flash
import zipfile
import os
from werkzeug.utils import secure_filename
from tempfile import TemporaryDirectory
import matplotlib.pyplot as plt
from cell_count import generate_plot
from cell_health import generate_graphs
from conversiontoGifMeijeringLabeled import createPlainCellGiffromObject, createSortedCellImageArray, generateMejerinRedLabel  # Import your generate_plot function here
from count_branch import generate_branch_plot

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # Add a secret key for session

@app.route('/')
def home():
    return render_template('home.html')

@app.route('/upload', methods=['POST'])
def upload():
    if 'zip_file1' not in request.files or 'zip_file2' not in request.files:
        flash('Please select two ZIP files.')
        return redirect(request.url)

    zip_file1 = request.files['zip_file1']
    zip_file2 = request.files['zip_file2']

    if zip_file1.filename == '' or not zip_file1.filename.endswith('.zip'):
        flash(f'Invalid ZIP file: {zip_file1.filename}')
        return redirect(request.url)

    if zip_file2.filename == '' or not zip_file2.filename.endswith('.zip'):
        flash(f'Invalid ZIP file: {zip_file2.filename}')
        return redirect(request.url)

    with TemporaryDirectory() as temp_dir1, TemporaryDirectory() as temp_dir2:
        zip_filename1 = secure_filename(zip_file1.filename)
        zip_filename2 = secure_filename(zip_file2.filename)

        zip_file_path1 = os.path.join(temp_dir1, zip_filename1)
        zip_file_path2 = os.path.join(temp_dir2, zip_filename2)

        zip_file1.save(zip_file_path1)
        zip_file2.save(zip_file_path2)

        # Create folders to extract the contents
        extract_folder1 = os.path.join('extracted_files', zip_filename1.split('.')[0])
        os.makedirs(extract_folder1, exist_ok=True)

        extract_folder2 = os.path.join('extracted_files', zip_filename2.split('.')[0])
        os.makedirs(extract_folder2, exist_ok=True)

        # Extract the contents of the ZIP files
        with zipfile.ZipFile(zip_file_path1, 'r') as zip_ref1, zipfile.ZipFile(zip_file_path2, 'r') as zip_ref2:
            zip_ref1.extractall(extract_folder1)
            zip_ref2.extractall(extract_folder2)

        return redirect('/results')

@app.route('/results')
def show_results():

        generate_plot('extracted_files/SHSY5Y_Rep_1/SHSY5Y Rep 1','cell_count_1')
        generate_plot('extracted_files/SHSY5Y_Rep_2/SHSY5Y Rep 2','cell_count_2')
        generate_graphs('extracted_files/SHSY5Y_Rep_1/SHSY5Y Rep 1','1')
        generate_graphs('extracted_files/SHSY5Y_Rep_2/SHSY5Y Rep 2','2')

        sortedArrayImage = createSortedCellImageArray('extracted_files/SHSY5Y_Rep_1/SHSY5Y Rep 1')
        cellpics = []
        for cellpic in sortedArrayImage:
             cellpics.append(generateMejerinRedLabel(cellpic))
        createPlainCellGiffromObject(cellpics,'SHSY5Y Rep 1')

        sortedArrayImage = createSortedCellImageArray('extracted_files/SHSY5Y_Rep_2/SHSY5Y Rep 2')
        cellpics = []
        for cellpic in sortedArrayImage:
             cellpics.append(generateMejerinRedLabel(cellpic))
        createPlainCellGiffromObject(cellpics,'SHSY5Y Rep 2')
        generate_branch_plot('extracted_files/SHSY5Y_Rep_1/SHSY5Y Rep 1','branch_count_1')
        generate_branch_plot('extracted_files/SHSY5Y_Rep_2/SHSY5Y Rep 2','branch_count_2')

        return render_template('results.html')

@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory('static', filename)

if __name__ == '__main__':
    app.run(debug=True)


# -*- coding: utf-8 -*-
# pip install discord.py watchdog

import discord
import os
import config
from watchdog.observers import Observer
from libs.FileChangeHandler import FileChangeHandler
from libs.vars import *

FILE_CMD = config.DIRECTORY + '/file_io/cmd.txt'

# 起動時に動作する処理
@client.event
async def on_ready():
    # 起動したらターミナルにログイン通知が表示される
    channel = client.get_channel(config.CHANNEL_ID)
    await channel.send(embed=discord.Embed(title=config.TEXT_HELLO, color=0x00ff00))

# メッセージ受信時に動作する処理
@client.event
async def on_message(message):
    channel = client.get_channel(config.CHANNEL_ID)
    # 指定チャンネルでの指定フォーマットの人間のメッセージのみ反応
    content = message.content.replace('？','?').replace('，',',').replace('、',',')
    if message.author.bot or message.channel != channel or content[0]!='?' or len(content)<2:
        return

    with open(FILE_CMD, encoding='utf-8') as f:
        s = f.read()
        if s and not s.startswith('empty'):
            await channel.send(config.TEXT_BUSY)
            return
    with open(FILE_CMD, mode='w', encoding='utf-8') as f:
        f.write(content[1:])
        set_waiting_message(await channel.send(config.TEXT_WAIT))
        set_prev_out_hash(None)

def generate_io_files():
    os.makedirs(config.DIRECTORY+'/file_io', exist_ok=True)
    if not os.path.isfile(FILE_CMD):
        with open(FILE_CMD, mode='w', encoding='utf-8') as f:
            f.write('empty')

def start():
    generate_io_files()
    event_handler = FileChangeHandler()
    observer = Observer()
    observer.schedule(event_handler, config.DIRECTORY+'/file_io')
    observer.start()
    client.run(config.TOKEN)

# Botの起動とDiscordサーバーへの接続
start()


#!/usr/bin/python
import rospy
import numpy as np
import cv_bridge
import cv2 as cv
import imutils
from sensor_msgs.msg import Image, PointCloud2, CameraInfo
from sensor_msgs.point_cloud2 import *
from sensor_msgs.point_cloud2 import _get_struct_fmt
from geometry_msgs.msg import PointStamped

RGB_TOPIC_PARAM="~camera_topic/rgb"
DEPTH_TOPIC_PARAM="~camera_topic/depth"
LOCATION_TOPIC_PARAM="~location_topic/kinect"
CAMERA_INFO_TOPIC_PARAM="~camera_topic/info"
BALL_FRAME_PARAM="~frame/ball"

class KinectImage:
    def __init__(self, img_topic, depth_topic, pub_topic, camera_info_topic, ball_frame, CALIBRATE_COUNT=150.0, robot_display_topic="/robot/xdisplay"):
        self.lastPC = None

        self.bridge = cv_bridge.CvBridge()
        self.background = cv.createBackgroundSubtractorMOG2()

        self.calibrate = 0
        self.CALIBRATE_COUNT = CALIBRATE_COUNT
        self.calibrated = False
        self.clicks = []

        self.rate = rospy.Rate(10)

        self.ball_frame = ball_frame
        try:
            cam_info = rospy.wait_for_message(camera_info_topic, CameraInfo)
        except:
            print("ERR")
            rospy.signal_shutdown("Error trying to get camera information")
        self.maxX, self.maxY = cam_info.width, cam_info.height
        self.minX, self.minY = 0, 0
        self.pub = rospy.Publisher(pub_topic, PointStamped)
        if robot_display_topic:
            self.robot_display_pub = rospy.Publisher(robot_display_topic, Image)
        else:
            self.robot_display_pub = None
        self.subscriber1 = rospy.Subscriber(img_topic, Image, self.imgCallback)
        self.subscriber2 = rospy.Subscriber(depth_topic, PointCloud2, self.depthCallback)

    def clickCallback(self, event, x, y, flag, param):
        if (event == cv.EVENT_LBUTTONUP):
            point = (x, y)
            self.clicks.append(point)

    def imgCallback(self, data):
        while not self.calibrated:
            cvImage = self.bridge.imgmsg_to_cv2(data, "bgr8")
            self.clicks = []
            cv.imshow("Choose Area of Interest", cvImage)
            while len(self.clicks) < 4:
                cv.setMouseCallback("Choose Area of Interest", self.clickCallback)
                key = cv.waitKey(10)
                if key == ord(' '):
                    rospy.loginfo("Using default")
                    self.clicks = []
                    self.calibrated = True
                    cv.destroyAllWindows()
                    return
            cv.destroyAllWindows()
            for point in self.clicks:
                cv.circle(cvImage, point, 3, (0, 255, 0), -1)
            cv.imshow("Confirm selection", cvImage)
            key = cv.waitKey(0)
            if key == ord(' '):
                self.minX = min([xy[0] for xy in self.clicks])
                self.minY = min([xy[1] for xy in self.clicks])
                self.maxX = max([xy[0] for xy in self.clicks])
                self.maxY = max([xy[1] for xy in self.clicks])
                rospy.loginfo("Calibrated X: %d - %d Y: %d - %d", self.minX, self.maxX, self.minY, self.maxY)
                self.calibrated = True
                cv.destroyAllWindows()
                return
            else:
                cv.destroyAllWindows()
        if self.lastPC is None:
            return
        cvImage = self.bridge.imgmsg_to_cv2(data, "bgr8")
        greenLower = (29, 86, 6)
        greenUpper = (64, 255, 255)

        frame = cvImage
        blurred = cv.GaussianBlur(frame, (11, 11), 0)
        hsv = cv.cvtColor(blurred, cv.COLOR_BGR2HSV)

        mask = cv.inRange(hsv, greenLower, greenUpper)
        mask = cv.erode(mask, None, iterations=2)
        mask = cv.dilate(mask, None, iterations=2)

        cnts = cv.findContours(mask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        # print("Center:",cnts)
        valid_cnts = []
        for cnt in grab_contours(cnts):
            ((x, y), radius) = cv.minEnclosingCircle(cnt)
            if x >= self.minX and x <= self.maxX and y >= self.minY and y <= self.maxY:
                valid_cnts.append(cnt)
        center = None

        # only proceed if at least one contour was found
        if len(valid_cnts) > 0:
		    # find the largest contour in the mask, then use
		    # it to compute the minimum enclosing circle and
		    # centroid
            c = max(valid_cnts, key=cv.contourArea)
            ((x, y), radius) = cv.minEnclosingCircle(c)
            M = cv.moments(c)
            center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

            # only proceed if the radius meets a minimum size
            if radius > 10:
                # draw the circle and centroid on the frame,
                # then update the list of tracked points
                cv.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2)
                cv.circle(frame, center, 5, (0, 0, 255), -1)
                p = PointStamped()
                p.point.y, p.point.z, p.point.x = getDepth(x, y, self.lastPC)
                p.point.y, p.point.z = -p.point.y, -p.point.z
                # p.point.x, p.point.y, p.point.z = x * 0.001, y * 0.001, getDepth(x, y, self.lastPC)[2]
                p.header.frame_id = self.ball_frame

                self.pub.publish(p)
        if self.robot_display_pub:
            self.robot_display_pub.publish(self.bridge.cv2_to_imgmsg(frame, encoding="bgr8"))
        cv.imshow("Frame", frame)
        key = cv.waitKey(1) & 0xFF

    def depthCallback(self, pc):
        self.lastPC = pc

def getDepth(x, y, lPC, numSamples=500, mu=0, sigma=10):
    # x -= 10
    # ptsX, ptsY, ptsD = np.array([]), np.array([]), np.array([])
    # for _ in range(numSamples):
    #     try:
    #         dx, dy = np.random.normal(mu, sigma, 2)
    #         # pts_gen = read_points(lPC, uvs=[(int(np.round(x + dx)), int(np.round(y + dy)))])
    #         # pt = next(pts_gen)
    #         pt = read_point(int(np.round(x + dx)), int(np.round(y + dy)), lPC)
    #         if not np.isnan(pt[0]):
    #             ptsX = np.append(ptsX, pt[0])
    #         if not np.isnan(pt[1]):
    #             ptsY = np.append(ptsY, pt[1])
    #         if not np.isnan(pt[2]):
    #             ptsD = np.append(ptsD, pt[2])
    #     except Exception as e:
    #         rospy.logerr("failed: %s", e)
    #         pass
    # return np.median(ptsX), np.median(ptsY), np.median(ptsD)
    pts = []
    for _ in range(numSamples):
        try:
            dx, dy = np.random.normal(mu, sigma, 2)
            pt = read_point(int(np.round(x + dx)), int(np.round(y + dy)), lPC)
            if not np.isnan(pt[0]) and not np.isnan(pt[1]) and not np.isnan(pt[2]):
                pts.append(pt)
        except:
            continue
    return min(pts, key=lambda x: x[2])

def read_point(x, y, cloud, field_names=None, skip_nans=False, uvs=[]):
    assert isinstance(cloud, roslib.message.Message) and cloud._type == 'sensor_msgs/PointCloud2', 'cloud is not a sensor_msgs.msg.PointCloud2'
    fmt = _get_struct_fmt(cloud.is_bigendian, cloud.fields, field_names)
    width, height, point_step, row_step, data, isnan = cloud.width, cloud.height, cloud.point_step, cloud.row_step, cloud.data, math.isnan
    unpack_from = struct.Struct(fmt).unpack_from
    offset = row_step * y + point_step * x
    return unpack_from(data, offset)

# Code from: https://github.com/jrosebr1/imutils/blob/5aae9887df3dcada5f8d8fa6af0df2122ad7aaca/imutils/convenience.py
# This is code from the imutils package that for whatever reason does not appear to
# be in the version on the lab computers.
def grab_contours(cnts):
    # if the length the contours tuple returned by cv2.findContours
    # is '2' then we are using either OpenCV v2.4, v4-beta, or
    # v4-official
    if len(cnts) == 2:
        cnts = cnts[0]
    # if the length of the contours tuple is '3' then we are using
    # either OpenCV v3, v4-pre, or v4-alpha
    elif len(cnts) == 3:
        cnts = cnts[1]
    # otherwise OpenCV has changed their cv2.findContours return
    # signature yet again and I have no idea WTH is going on
    else:
        raise Exception(("Contours tuple must have length 2 or 3, "
            "otherwise OpenCV changed their cv2.findContours return "
            "signature yet again. Refer to OpenCV's documentation "
            "in that case"))
    # return the actual contours array
    return cnts

def main():
    rospy.init_node('kinect_image', log_level=rospy.DEBUG)
    if not rospy.has_param(RGB_TOPIC_PARAM):
        rospy.logerr("Couldn't find parameter %s", RGB_TOPIC_PARAM)
        exit(1)
    if not rospy.has_param(DEPTH_TOPIC_PARAM):
        rospy.logerr("Couldn't find parameter %s", DEPTH_TOPIC_PARAM)
        exit(1)
    if not rospy.has_param(LOCATION_TOPIC_PARAM):
        rospy.logerr("Couldn't find parameter %s", LOCATION_TOPIC_PARAM)
        exit(1)
    if not rospy.has_param(BALL_FRAME_PARAM):
        rospy.logerr("Couldn't find parameter %s", BALL_FRAME_PARAM)
        exit(1)
    if not rospy.has_param(CAMERA_INFO_TOPIC_PARAM):
        rospy.logerr("Couldn't find parameter %s", CAMERA_INFO_TOPIC_PARAM)
        exit(1)
    rgb = KinectImage(
        rospy.get_param(RGB_TOPIC_PARAM),
        rospy.get_param(DEPTH_TOPIC_PARAM),
        rospy.get_param(LOCATION_TOPIC_PARAM),
        rospy.get_param(CAMERA_INFO_TOPIC_PARAM),
        rospy.get_param(BALL_FRAME_PARAM))
    rospy.spin()
    rgb.subscriber1.unregister()
    rgb.subscriber2.unregister()

if __name__=='__main__':
    main()


#!/usr/bin/env python3

from bayes_opt import BayesianOptimization

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import axes3d, Axes3D
import numpy as np

def my_func(x, y):

    # print('x: {}'. format(x))
    return -(np.sin((np.power(x, 2) + np.power(y, 2)) ) + 0.1 * np.power(x-4, 3))
    #np.sin( 10*(np.power(x, 2)+np.power(y,2)) ) / 10 + 0.1 * np.power(x-4, 1.1)

pbounds = {'x': (2.0, 6.0), 'y': (2.0, 6.0)}

optimizer = BayesianOptimization(
    f=my_func,
    pbounds=pbounds,
    verbose=2, # verbose = 1 prints only when a maximum is observed, verbose = 0 is silent
    random_state=1,
)

optimizer.maximize(
    init_points=20,
    n_iter=100,
)

print(optimizer.max)

# plot
fig = plt.figure()
ax = Axes3D(fig)

x = np.arange(1.5, 6.0, 0.01)
y = np.arange(2.0, 6.0, 0.01)

X, Y = np.meshgrid(x,x)

z = my_func(X, Y)

res_x = optimizer.max['params']['x']
res_y = optimizer.max['params']['y']
ax.scatter(
    res_x,
    res_y,
    my_func(res_x, res_y),
    s=128,
    c='red',
    alpha=1
    )
ax.plot_surface(X, Y, my_func(X, Y))

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()


from app import config

def smartsheet_log_signup(customer_id, signup_time, message):
    """
    Create row in smartsheet based on environment variables
    """

    if (not config.SMARTSHEET_TOKEN) or (not config.SMARTSHEET_SIGNUP_SHEET):
        return None

    import smartsheet

    smartsheet_api = smartsheet.Smartsheet(config.SMARTSHEET_TOKEN)
    action = smartsheet_api.Sheets.list_sheets(include_all=True)
    sheets = action.data
    for sheetInfo in sheets:
        if sheetInfo.name == config.SMARTSHEET_SIGNUP_SHEET:
            sheet = smartsheet_api.Sheets.get_sheet(sheetInfo.id)
            break

    else:
        print("Failed logging signup from %s. A smartsheet named %s wasn't found under token %s"
                % (customer_id, config.SMARTSHEET_SIGNUP_SHEET, config.SMARTSHEET_TOKEN))

    cols = smartsheet_api.Sheets.get_columns(sheetInfo.id)
    row = smartsheet_api.models.Row()
    row.to_top = True
    row.cells.append({
            'column_id': cols[config.SMARTSHEET_COL_SIGNUP_TIME],
            'value': signup_time,
            'strict': False
        },
        {
            'column_id': cols[config.SMARTSHEET_COL_CUSTOMER_ID],
            'value': customer_id,
            'strict': False
        },
        {
            'column_id': cols[config.SMARTSHEET_COL_MESSAGE],
            'value': message,
            'strict': False
        },
    )

    return smartsheet_api.Sheets.add_rows(sheetInfo.id, [row])


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

import numpy as np
import pandas as pd
import sys, math
import matplotlib.pyplot as plt

def pettitt(X):
	# second one
	U = []; s = 0
	U.append(sum(np.sign(X[0] - np.array(X[:]))))
	for t in range(1, len(X)):
		v_t = sum(np.sign(X[t] - np.array(X[:])))
		U.append(U[t-1] + v_t)
	Kt = max(np.abs(U))
	max_idx = list(np.abs(U)).index(max(np.abs(U)))
	return U, max_idx, Kt

def plot(X, Ut, Kt, max_idx):
	fig = plt.figure(figsize = (9, 6))
	plt.subplots_adjust(left=0.1, right=0.9, top=0.98, bottom=0.05, wspace=None, hspace=0.5)
	axes = []
	for i in range(2):
		ax = fig.add_subplot(2, 1, i + 1)
		axes.append(ax)
	# 原始数据
	axes[0].plot(range(1, len(X) + 1), X)
	axes[0].plot([max_idx + 1, max_idx + 1], [min(X) - 0.5, max(X) + 0.5], linestyle = "--", c = "r")
	# axes[0].set_xlabel("Index")
	axes[0].set_ylabel("X")
	axes[0].set_xlim((0 - 1, len(X) + 1))
	axes[0].set_ylim((min(X) - 0.5, max(X) + 0.5))

	axes[1].plot(range(1, len(Ut) + 1), np.abs(Ut), label = "Ut")
	axes[1].plot([max_idx + 1, max_idx + 1], [0, Kt], linestyle = "--", c = "r")

	Kt_005, Kt_005_n = CalKtByAlpha(0.05, len(X))
	axes[1].plot([1, len(Ut)], [Kt_005, Kt_005], linestyle = "-.", c = "r")
	axes[1].plot([1, len(Ut)], [Kt_005_n, Kt_005_n], linestyle = "-.", c = "r", label = "p=0.05")

	Kt_001, Kt_001_n = CalKtByAlpha(0.01, len(X))
	axes[1].plot([1, len(Ut)], [Kt_001, Kt_001], linestyle = "--", c = "b")
	axes[1].plot([1, len(Ut)], [Kt_001_n, Kt_001_n], linestyle = "--", c = "b", label = "p=0.01")

	Kt_0001, Kt_0001_n = CalKtByAlpha(0.001, len(X))
	axes[1].plot([1, len(Ut)], [Kt_0001, Kt_0001], linestyle = ":", c = "g")
	axes[1].plot([1, len(Ut)], [Kt_0001_n, Kt_0001_n], linestyle = ":", c = "g", label = "p=0.001")

	axes[1].set_xlim((0 - 1, len(X) + 1))
	axes[1].set_ylabel("Ut")
	plt.legend(loc = "upper left")
	plt.show()

def CalP(Kt, n):
	return 2.0 * math.exp((-6.0 * Kt ** 2) / float(n ** 3 + n ** 2))

def CalKtByAlpha(alpha, n):
	Kt = math.sqrt(np.log(alpha / 2.0) / -6.0 * (n ** 3 + n ** 2))
	return Kt, -Kt

def main():
	alpha = 0.05
	data = pd.read_csv("data_random.csv")
	Year = list(data["Year"])
	X = list(data["X"])

	Ut, max_idx, Kt = pettitt(X)
	print("The %dth sample is change point. Kt=%.2f, Year:%d, p=%.5f" % (max_idx + 1, Kt, Year[max_idx], CalP(Kt, len(X))))
	if CalP(Kt, len(X)) < alpha:
		print("The %dth sample is change point. Year:%d, p=%.9f" % (max_idx + 1, Year[max_idx], CalP(Kt, len(X))))
	else:
		print("Does not satisfy the significance level! P(Kt) = %.5f" % CalP(Kt, len(X)))
	plot(X, Ut, Kt, max_idx)

if __name__ == '__main__':
	main()


"""
    This script connects to Twitter Streaming API, gets tweets with '#' and
    forwards them through a local connection in port 9009. That stream is
    meant to be read by a spark app for processing. Both apps are designed
    to be run in Docker containers.

    To execute this in a Docker container, do:

        docker run -it -v $PWD:/app --name twitter -p 9009:9009 python bash

    and inside the docker:

        pip install -U git+https://github.com/tweepy/tweepy.git
        python twitter_app.py

    (we don't do pip install tweepy because of a bug in the previous release)
    For more instructions on how to run, refer to final slides in tutorial 8

    Made for: EECS 4415 - Big Data Systems (York University EECS dept.)
    Author: Tilemachos Pechlivanoglou

"""

# from __future__ import absolute_import, print_function

import socket
import sys
import json

from tweepy.streaming import StreamListener
from tweepy import OAuthHandler
from tweepy import API
from tweepy import Stream

# Replace the values below with yours
consumer_key="xxxxxx"
consumer_secret="xxxxxx"
access_token="xxxxxx"
access_token_secret="xxxxxx"

class TweetListener(StreamListener):
    """ A listener that handles tweets received from the Twitter stream.

        This listener prints tweets and then forwards them to a local port
        for processing in the spark app.
    """

    def on_data(self, data):
        """When a tweet is received, forward it"""
        try:

            global conn

            # load the tweet JSON, get pure text
            full_tweet = json.loads(data)
            tweet_text = full_tweet['text']

            # print the tweet plus a separator
            print ("------------------------------------------")
            print(tweet_text + '\n')

            # send it to spark
            conn.send(str.encode(tweet_text + '\n'))
        except:

            # handle errors
            e = sys.exc_info()[0]
            print("Error: %s" % e)

        return True

    def on_error(self, status):
        print(status)

# ==== setup local connection ====

# IP and port of local machine or Docker
TCP_IP = socket.gethostbyname(socket.gethostname()) # returns local IP
TCP_PORT = 9009

# setup local connection, expose socket, listen for spark app
conn = None
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
print("Waiting for TCP connection...")

# if the connection is accepted, proceed
conn, addr = s.accept()
print("Connected... Starting getting tweets.")

# ==== setup twitter connection ====
listener = TweetListener()
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
stream = Stream(auth, listener)

# setup search terms
# "#dowjones", "#sp500", "#bitcoin" , "#nasdaq100", "#aapl"
# track = ['#dowjones', '#sp500', '#bitcoin', '#nasdaq100', '#aapl']
# topics = ['#basketball', '#baseball', '#cricket', '#soccer', '#tennis']
# basketball_hashtags = ['#NBA', '#raptors', '#lakers', '#jordan', '#warriors', '#stephcurry', '#dunk', '#bball', '#kaizen', '#hoops']
# baseball_hashtags = ['#bluejays', '#RonaldAcuna', '#atlanta', '#rookiecard', '#beisbol', '#mlb', '#nfl', '#mikeTrout', '#mookie', '#derekJeter']
# cricket_hashtags = ['#pakistan', '#babarAzam', '#worldCup', '#kohli', '#dhoni', '#batting', '#bowlingmachine', '#ipl', '#cricketnation', '#pitch']
# soccer_hashtags = ['#worldCup', '#championsLeague', '#messi', '#ronaldo', '#cr7', '#manchesterUnited', '#barcelona', '#realMadrid', '#chelsea', '#neymarJR']
# tennis_hashtags = ['#rogerFederer', '#rogersCup', '#wimbledon', '#Federer', '#davisCupMadridFinals', '#novak', '#saniaMirza', '#nadal', '#davisCup', '#serenaWilliams']
# hashtags_list = basketball_hashtags + baseball_hashtags + cricket_hashtags + soccer_hashtags + tennis_hashtags

lakers = ['#lakers', '#lal', '#lbj', '#lakernation', '#lebron', '#lebronjames', '#kobe', '#losangeleslakers', '#lalakers', '#anthonydavis']
raptors = ['#raptors', '#torontoraptors', '#wethenorth', '#kylelowry', '#siakam', '#raptornation', '#nabchamps2019','#freddy', '#steadyfreddy', '#raptorswin']
knicks = ['#nyknicks', '#knicks', '#knicksfan' ,'#knickstape', '#knicksnation', '#newyorkknicks', '#msg', '#nyknicksbasketball', '#rjbarrett', '#nyk']
warriors = ['#warriors', '#goldenstatewarriors', '#stephcurry', '#stephencurry', '#dubnation', '#gsw', '#warriorsnation', '#klaythompson', '#deangelorussell', '#warriorsground']
bulls = ['#chicagobulls', '#bulls' ,'#jordan' , '#michaeljordan' , '#bullsnation', '#bullsoutsiders', '#zachlavine', '#firegarpax', '#bullswin', '#scottiepippen']
hashtags = lakers + raptors + knicks + warriors + bulls

language = ['en']
locations = [-130,-20,100,50]

# get filtered tweets, forward them to spark until interrupted
try:
    stream.filter(track=hashtags)
except KeyboardInterrupt:
    s.shutdown(socket.SHUT_RD)


import sieve
from typing import Dict, List

@sieve.function(
    name="transcript_analyzer",
    python_packages=[
        "gpt-json"
    ],
    python_version="3.10",
    environment_variables=[
        sieve.Env(name="OPENAI_API_KEY", description="OpenAI API Key"),
        sieve.Env(name="NUM_TAGS", description="Number of tags to generate", default="5"),
        sieve.Env(name="MAX_SUMMARY_SENTENCES", description="Number of sentences to summarize", default="5"),
        sieve.Env(name="MAX_TITLE_WORDS", description="Max number of words in title", default="10"),
    ]
)
def analyze_transcript(transcript):
    yield {"transcript": transcript}
    import time
    overall_start_time = time.time()
    import os
    import json
    import asyncio

    from transcript_analysis import description_runner, chapter_runner

    max_num_sentences = int(os.getenv("MAX_SUMMARY_SENTENCES", 5))
    max_num_words = int(os.getenv("MAX_TITLE_WORDS", 10))
    num_tags = int(os.getenv("NUM_TAGS", 5))
    summary, title, tags = asyncio.run(description_runner(transcript, max_num_sentences=max_num_sentences, max_num_words= max_num_words, num_tags=num_tags))
    yield {"summary": summary}
    yield {"title": title}
    yield {"tags": tags}

    chapters = asyncio.run(chapter_runner(transcript))
    out_list = []
    for chapter in chapters:
        out_list.append({"title": chapter.title, "start_time": chapter.start_time})
    yield {"chapters": out_list}

@sieve.function(name="extract_audio", system_packages=["ffmpeg"])
def split_audio(vid: sieve.Video) -> sieve.Audio:
    import time
    overall_start_time = time.time()
    import subprocess
    video_path = vid.path

    audio_path = 'temp.wav'

    # overwrite existing file and turn into wav
    subprocess.run(["ffmpeg", "-i", video_path, audio_path, "-y"])
    print(f"Overall time: {time.time() - overall_start_time}")
    return sieve.Audio(path=audio_path)

wf_metadata = sieve.Metadata(
    title="Video Transcript Analysis",
    description="Given a video, generate a title, chapters, summary and tags",
    code_url="https://github.com/sieve-community/examples/tree/main/video_transcript_analysis/main.py",
    tags=["Video"],
    image=sieve.Image(
        url="https://www.tubebuddy.com/wp-content/uploads/2022/06/video-chapter-snippet-1024x674.png"
    ),
    readme=open("README.md", "r").read(),
)

@sieve.workflow(name="video_transcript_analysis", metadata=wf_metadata)
def video_analysis(vid: sieve.Video) -> List[Dict]:
    """
    :param vid: A video to transcribe and analyze
    :return: A title, summary, tags, and chapters
    """
    audio = split_audio(vid)
    text = sieve.reference("sieve/whisperx")(audio)
    analysis = analyze_transcript(text)
    return analysis

if __name__ == "__main__":
    sieve.push(
        workflow="video_transcript_analysis",
        inputs={
            "vid": {
                "url": "https://storage.googleapis.com/sieve-public-videos-grapefruit/The%20Truth%20About%20AI%20Getting%20Creative.mp4"
            }
        },
    )


class largerKey(str):
    def __lt__(x,y):
        return x+y>y+x

class Solution:
    def largestNumber(self, nums: List[int]) -> str:
        #comparing
        #for i, n in enumerate(nums):
        #   nums[i]=str(n)
        def compare(n1,n2):
            if n1+n2>n2+n1:
                return -1 # return n1 at start
            else:
                return 1
        nums=list(map(str,nums))
        nums=sorted(nums,key=cmp_to_key(compare))
        return str(int("".join(nums)))

        largest_num=''.join(sorted(map(str,nums),key=largerKey))
        return '0' if largest_num[0]=="0" else largest_num


#!/usr/bin/env python3
# https://arc095.contest.atcoder.jp/tasks/arc095_b
n = int(input())
a = [int(x) for x in input().split()]
a.sort()
y = a[-1]
m = None
x = None
for i in range(n - 1):
    k = a[i]
    l = max(k, y - k)
    if m is None or m > l:
        m = l
        x = k
print(y, x)


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

from dataiku.customrecipe import get_recipe_config

from dku_timeseries import Resampler
from io_utils import get_input_output
from recipe_config_loading import check_and_get_groupby_columns, check_time_column_parameter, check_python_version, get_resampling_params

check_python_version()

# --- Setup
(input_dataset, output_dataset) = get_input_output()
recipe_config = get_recipe_config()
input_dataset_columns = [column["name"] for column in input_dataset.read_schema()]
check_time_column_parameter(recipe_config, input_dataset_columns)
groupby_columns = check_and_get_groupby_columns(recipe_config, input_dataset_columns)
datetime_column = recipe_config.get('datetime_column')
params = get_resampling_params(recipe_config)

# --- Run
df = input_dataset.get_dataframe()
resampler = Resampler(params)
output_df = resampler.transform(df, datetime_column, groupby_columns=groupby_columns)

# --- Write output
output_dataset.write_with_schema(output_df)


import tensorflow as tf
import h5py, os
import vis_utils, argparse

@tf.function
def orient_point_cloud(x_batch, rot_random_batch, rot_can):

    '''
    B, N, 3
    B, 3, 3
    '''

    rot_random = tf.tile(rot_random_batch, [x_batch.shape[0], 1, 1])
    # print(rot_random.shape)
    x_batch_rotated = tf.einsum("bij,bkj->bki", rot_random, x_batch)
    x_batch_canonical = tf.einsum("bij,bkj->bki", rot_can, x_batch_rotated)

    return x_batch_canonical, x_batch_rotated

def save_vis_point_cloud(x_file, rot_random_file, rot_can_file, batch_size = 32, num_rots = 120, output_directory = "./pointclouds", total_clouds = None):

    output_directory = os.path.join(output_directory,"")

    if not os.path.exists(output_directory):
        os.makedirs(output_directory)

    x = h5py.File(x_file, "r")["data"][:]
    rot_random = h5py.File(rot_random_file, "r")["data"][:]
    rot_can = h5py.File(rot_can_file, "r")["data"][:]

    num_rots_temp = min(rot_can.shape[1], rot_random.shape[0])
    num_rots = min(num_rots, num_rots_temp)
    total_shapes = x.shape[0]
    batch_num = 0

    while (batch_num * batch_size <= total_shapes):
        remaining = total_shapes - batch_num * batch_size

        for rot_num in range(num_rots):

            if remaining < batch_num * batch_size:
                input_shape = x[batch_num * batch_size: total_shapes]
                input_can_rot = rot_can[batch_num * batch_size: total_shapes]
            else:
                input_shape = x[batch_num * batch_size: (batch_num + 1)*batch_size]
                input_can_rot = rot_can[batch_num * batch_size: (batch_num + 1)*batch_size]

            input_rot_random = rot_random[rot_num: (rot_num + 1)] # 1 x 3 x 3
            result, result_rotated = orient_point_cloud(input_shape, input_rot_random, input_can_rot[:, rot_num])

            for save_id in range(result.shape[0]):
                idx = batch_num * batch_size + save_id
                vis_utils.save_pointcloud(result[save_id:save_id+1], output_directory + "%d_canonical_pointcloud_full_rot_%d.ply" % (idx, rot_num))
                vis_utils.save_pointcloud(result_rotated[save_id:save_id+1], output_directory + "%d_input_full_%d.ply" % (idx, rot_num))

            if total_clouds is not None:
                if batch_num * batch_size > total_clouds:
                    return

        batch_num += 1

if __name__=="__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("--rot_random", required = True, type = str)
    parser.add_argument("--shape", required = True, type = str)
    parser.add_argument("--rot_can", required = True, type = str)
    parser.add_argument("--batch_size", type = int, default = 8)
    parser.add_argument("--output", type=str, required = True)
    parser.add_argument("--num_rots", type=int, default = 120)
    parser.add_argument("--total_clouds", type=int, default = None)

    args = parser.parse_args()

    save_vis_point_cloud(args.shape, args.rot_random, args.rot_can, args.batch_size, args.num_rots, args.output, args.total_clouds)


from collections import deque
from typing import Optional, List

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        # res = []
        #
        # q = deque()
        # q.append([root, 0])
        #
        # while q:
        #     node, level = q.popleft()
        #
        #     if len(res) <= level:
        #         res.append([node.val])
        #     else:
        #         res[level].append(node.val)
        #
        #     if node.left:
        #         q.append([node.left, level + 1])
        #     if node.right:
        #         q.append([node.right, level + 1])
        #
        # return res
        if not root:
            return []

        res = []

        def dfs(node, level):
            if len(res) <= level:
                res.append([node.val])
            else:
                res[level].append(node.val)

            if node.left:
                dfs(node.left, level + 1)
            if node.right:
                dfs(node.right, level + 1)

        dfs(root, 0)

        return res

if __name__ == "__main__":
    root = TreeNode(3, TreeNode(9), TreeNode(20, TreeNode(15), TreeNode(7)))
    assert Solution().levelOrder(root) == [[3], [9, 20], [15, 7]]
    root = TreeNode(1)
    assert Solution().levelOrder(root) == [[1]]


##################################################
# Tools used to capture images and save them
##################################################
# GNU GENERAL PUBLIC LICENSE
##################################################
# Author: Michael Bowyer
# Maintainer: Michael Bowyer
# Email: mbowyer@umich.edu
# License: GNU GENERAL PUBLIC LICENSE
##################################################

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.patches as mpatches
from lib import fuzzy_clustering as fcm

def saveClusteredImg(img, brightestClustIDs, fileName, imgCenter, brightClustCenter, saveImg, showImg):
    # Establish color map
    colorMap = fcm.createColorMap(brightestClustIDs)

    plt.figure("2) Clustered Image")
    # Create image to save
    ax = plt.gca()
    plt.cla()
    ax.imshow(img, cmap=colorMap)
    clusterCenterCircle = patches.Circle((brightClustCenter[0], brightClustCenter[1]), 4, linewidth=1,
                                         edgecolor='r', facecolor='r', label="Bright cluster center")
    ax.add_patch(clusterCenterCircle)
    imgCenterCircle = patches.Circle((imgCenter[0], imgCenter[1]), 4, linewidth=1,
                                     edgecolor='g', facecolor='g', label="Image center")
    ax.add_patch(imgCenterCircle)

    # Create Title
    brightStr = "Image center coordinates: ({}, {})".format(
        imgCenter[0], imgCenter[1])
    centerStr = "Bright cluster center coordinates: ({}, {})".format(
        brightClustCenter[0], brightClustCenter[1])
    correctionStc = "Difference between centers: ({}, {})".format(
        brightClustCenter[0] - imgCenter[0], brightClustCenter[1] - imgCenter[1])
    textstr = '\n'.join((brightStr, centerStr, correctionStc))
    plt.title(textstr)

    # Create Legend
    whitePatch = mpatches.Patch(color='white', label='Brightest cluster')
    greyPatch = mpatches.Patch(color='grey', label='Semi-bright cluster')
    blackPatch = mpatches.Patch(color='black', label='Dark cluster')
    legend1 = ax.legend(handles=[whitePatch, greyPatch, blackPatch],
                        bbox_to_anchor=(1.35, 1), facecolor='moccasin')
    legend2 = ax.legend(handles=[clusterCenterCircle, imgCenterCircle],
                        bbox_to_anchor=(1.35, .8), facecolor='moccasin')
    # Manually add the first legend back
    ax.add_artist(legend1)
    # save image
    if(saveImg):
        plt.savefig(fileName, bbox_inches='tight')
    if(showImg):
        # plt.figure("2) Clustered Image")
        plt.tight_layout()
        plt.draw()
        plt.pause(0.001)

def capturePic(cam):
    ret = 0
    image = 0
    latestImg = 0
    for i in range(0, 4):
        cam.grab()
    ret, image = cam.read()
    return ret, image

def warmUpCamera(cam):
    ret = 0
    image = 0
    for i in range(0, 10):
        ret, image = cam.read()
    return ret, image


import traceback
import re

from plugins import CampyPlugin
from campy import settings

from httplib import HTTPConnection, HTTPSConnection
from urllib import quote

try:
    import json
except ImportError:
    import simplejson as json

class Twitter(CampyPlugin):

    def send_help(self, campfire, room, message, speaker):
        help_text = '%s: twitter handle' % speaker['user']['name']
        room.paste(help_text)

    def handle_message(self, campfire, room, message, speaker):
        body = message['body']
        if not body:
            return

        if not body.startswith(settings.CAMPFIRE_BOT_NAME):
            return

        m = re.match('%s: twitter (?P<handle>.*)$' % \
                settings.CAMPFIRE_BOT_NAME, body)
        if m:
            try:
                screen_name = m.group('handle')

                conn = HTTPConnection('api.twitter.com')
                conn.request('GET', '/1/users/show.json?screen_name=%s' %
                                    quote(screen_name))
                resp = conn.getresponse()
                r = resp.read()
                conn.close()
                request = json.loads(r)
                if 'status' in request:
                    room.fetch_tweet('http://twitter.com/#!/%s/status/%s' % \
                            (screen_name, request['status']['id']))
                else:
                    room.speak('I cannot find anything for @%s.' % screen_name)
            except (KeyError,):
                room.speak(traceback.format_exc())


from telegram import (
    ReplyKeyboardMarkup,
    ReplyKeyboardRemove, Update,
    InlineKeyboardButton, InlineKeyboardMarkup
)
from telegram.ext import (
    CommandHandler, CallbackContext,
    ConversationHandler, MessageHandler,
    Filters, Updater, CallbackQueryHandler
)
from config import (
    TOKEN, api_key, sender_email,
    api_secret, sendgrid_key
)
import re
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import IntegrityError
from models import engine, User, Business, Category, Product
import cloudinary
from cloudinary.uploader import upload
from apscheduler.schedulers.background import BackgroundScheduler
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
from helpers import emailcheck
import time

Session = sessionmaker(bind=engine)
session = Session()
sched = BackgroundScheduler()

updater = Updater(token=TOKEN, use_context=True)
dispatcher = updater.dispatcher

def dispatch_mail():
    emails = [
        i.email for i in session.query(User).all() if i.is_smeowner and emailcheck(i.email)
    ]
    print(emails)
    with open('email.html', 'r') as file:
        msg = Mail(
            from_email=(sender_email, 'Paul From SmeBot'),
            to_emails=emails,
            subject="Welcome to smebot! - Next Steps",
            html_content=file.read()
        )
    try:
        client = SendGridAPIClient(sendgrid_key).send(msg)
        print(client.status_code)
        print("Done!..")
    except Exception as e:
        print(e.message)

# configure cloudinary
cloudinary.config(
    cloud_name="curiouspaul",
    api_key=api_key,
    api_secret=api_secret
)

# Define Options
FETCH_PREFERENCES, CHOOSESME_CAT, FETCH_SUBPREFERENCE, \
    CLASS_STATE, SME_DETAILS, FETCH_UPDATES, \
    CHOOSING, ADD_PRODUCTS, FETCH_SMECONTACT = range(9)

reply_keyboard = [
    [
        InlineKeyboardButton(
            text="SME",
            callback_data="SME"
        ),
        InlineKeyboardButton(
            text="Customer",
            callback_data="Customer"
        )
    ]
]
markup = InlineKeyboardMarkup(reply_keyboard, one_time_keyboard=True)

# Define callback handler
def start(update, context: CallbackContext) -> int:
    global name
    if update.message.from_user.first_name is None:
        name = update.message.from_user.last_name
    elif update.message.from_user.last_name is None:
        name = update.message.from_user.first_name
    else:
        name = update.message.from_user.first_name + ' ' + \
            update.message.from_user.last_name
    user_ = session.query(User).filter_by(name=name).first()
    if user_ is not None:
        global owner
        owner = user_
        if user_.is_smeowner:
            if user_.sme.category:
                button = [[
                    InlineKeyboardButton(
                        text="Add new products",
                        callback_data=user_.sme.category.name
                    )
                ]]
                update.message.reply_text(
                    "Welcome back, what do you want to do",
                    reply_markup=InlineKeyboardMarkup(button)
                )
                return ADD_PRODUCTS
        else:
            global customer
            global pref
            customer = user_
            pref = customer.preference
            button = [[
                InlineKeyboardButton(
                    text="View Businesses",
                    callback_data='customer'
                )
            ]]
            update.message.reply_text(
                "Welcome back, what do you want to do",
                reply_markup=InlineKeyboardMarkup(button)
            )
            return CHOOSING
    else:
        print("You called")
        update.message.reply_text(
            "Hi fellow, Welcome to SMEbot ,"
            "Please tell me about yourself, "
            "provide your full name, email, and phone number, "
            "separated by comma each e.g: "
            "John Doe, JohnD@gmail.com, +234567897809"
        )
        return CLASS_STATE

def classer(update, context):
    print(name)
    data = update.message.text.split(',')
    print(data)
    if len(data) < 3 or len(data) > 3:
        update.message.reply_text(
            "Invalid entry, please make sure to input the details "
            "as requested in the instructions"
        )
        update.message.reply_text(
            "Type /start, to restart bot"
        )
        return ConversationHandler.END
    else:
        new_user = User(
            name=name, email=data[1],
            telephone=data[2]
        )
        session.add(new_user)
        try:
            session.commit()
        except IntegrityError:
            update.message.reply_text(
                "User with email already exists, try again"
            )
            print("Error: Duplicate data")
            session.rollback()
            return CLASS_STATE
        global customer
        customer = new_user
        update.message.reply_text(
            text="Collected information succesfully!..🎉🎉 \n"
            "Which of the following do you identify as ?",
            reply_markup=markup
        )
        return CHOOSING

def customer_details(update, context: CallbackContext) -> int:
    #print(update.callback_query.data.lower() == 'sme')
    if update.callback_query.data.lower() == 'sme':
        global owner
        user = update.callback_query.message.from_user
        # find user in db
        print(name)
        owner = session.query(User).filter_by(name=name).first()
        owner.is_smeowner = True
        session.commit()
        update.callback_query.message.reply_text(
            f"Great! {user.first_name}, please tell me about your business, "
            "provide your BrandName, Brand email, Address, and phone number"
            "in that order, each separated by comma(,) each e.g: "
            "JDWears, JDWears@gmail.com, 101-Mike Avenue-Ikeja, +234567897809",
            reply_markup=ReplyKeyboardRemove()
        )

        return CHOOSESME_CAT
    categories = [
        [
            InlineKeyboardButton(
                text="Clothing/Fashion",
                callback_data="Clothing/Fashion"
            ),
            InlineKeyboardButton(
                text="Hardware Accessories",
                callback_data="Hardware Accessories"
            )
        ],
        [
            InlineKeyboardButton(
                text="Food/Kitchen Ware",
                callback_data="Food/Kitchen Ware"
            ),
            InlineKeyboardButton(
                text="ArtnDesign",
                callback_data="ArtnDesign"
            )
        ]
    ]
    # categories = [
    #     ['Clothing/Fashion', 'Hardware Accessories'],
    #     ['Food/Kitchen Ware', 'ArtnDesign']
    # ]
    # markup = ReplyKeyboardMarkup(categories, one_time_keyboard=True)
    update.callback_query.message.reply_text(
        "Here's a list of categories available"
        "Choose one that matches your interest",
        reply_markup=InlineKeyboardMarkup(categories)
    )

    return FETCH_PREFERENCES

def fetch_preference(update, context: CallbackContext) -> int:
    if update.callback_query.data:
        choice = update.callback_query.data
        result = session.query(Category).filter_by(name=choice).first().sme
        if len(result) < 1:
            button = [[
                InlineKeyboardButton(
                    text="Select another Category?",
                    callback_data="customer"
                )
            ]]
            update.callback_query.message.reply_text(
                "Nothing here yet",
                reply_markup=InlineKeyboardMarkup(button)
            )
            return CHOOSING
        for i in result:
            button = [
                [
                    InlineKeyboardButton(
                        text='View Products',
                        callback_data=i.name
                    )
                ],
                [
                    InlineKeyboardButton(
                        text="Select for updates",
                        callback_data='pref'+','+i.name
                    )
                ]
            ]
            biz = session.query(Business).filter_by(name=i.name).first()
            #print(biz.product)
            if len(biz.product) > 0:
                ref = biz.product[0]
                #print(ref.image)
                update.callback_query.message.reply_photo(
                    photo=ref.image,
                    caption=f"{i.name}".upper(),
                    reply_markup=InlineKeyboardMarkup(button)
                )
            else:
                update.callback_query.message.reply_text(
                    f"{i.name}".upper(),
                    reply_markup=InlineKeyboardMarkup(button)
                )
    return FETCH_SUBPREFERENCE

def fetch_bizpref(update, context):
    if 'pref' in update.callback_query.data:
        choice = update.callback_query.data.split(',')
        customer.preference += choice[1] + ', '
        biz = session.query(Business).filter_by(name=choice[1]).first()
        session.commit()
        button = [
            [
                InlineKeyboardButton(
                    text="View more Businesses in same category",
                    callback_data=biz.category.name
                )
            ]
        ]
        update.callback_query.message.reply_text(
            "Preference set successfully 🎉",
            reply_markup=InlineKeyboardMarkup(button)
        )
        getupdates(update, context)
        return FETCH_PREFERENCES
    else:
        choice = update.callback_query.data
        biz = session.query(Business).filter_by(name=choice).first().product
        if biz and len(biz) < 1:
            button = [[
                InlineKeyboardButton(
                    text="View other businesses",
                    callback_data=biz.category.name
                )
            ]]
            update.callback_query.message.reply_text(
                "Nothing here yet",
                reply_markup=InlineKeyboardMarkup(button)
            )
            return FETCH_PREFERENCES
        for i in biz:
            update.callback_query.message.reply_photo(
                photo=i.image,
                caption=f"{i.name} \nDescription: {i.description}\nPrice:{i.price}"
            )
            update.callback_query.message.reply_text(
                "Contact business",
                reply_markup=InlineKeyboardMarkup(
                    [[InlineKeyboardButton(
                        text="Contact-Business-Owner",
                        callback_data=i.sme.owner.email
                    )]]
                )
            )
        biz = session.query(Business).filter_by(name=choice).first()
        button = [
            [
                InlineKeyboardButton(
                    text="View more Businesses in same category",
                    callback_data=biz.category.name
                )
            ]
        ]
        update.callback_query.message.reply_text(
            text="Done..?",
            reply_markup=InlineKeyboardMarkup(button)
        )
        return FETCH_SMECONTACT

def smecontact(update, context):
    check = [i.name.lower() for i in session.query(Category).all()]
    print(update.callback_query.data.lower() in check)
    if update.callback_query.data.lower() in check:
        return fetch_preference(update, context)
    data = update.callback_query.data
    data = session.query(User).filter_by(email=data).first()
    update.callback_query.message.reply_text(
        f"Telephone: {data.telephone}, "
        f"Email: {data.email}"
    )
    return -1

def getupdates(update, context):
    print("Called")
    result = []
    print(result)
    pref = customer.preference.split(',')
    print(pref)
    for i in pref:
        biz = session.query(Business).filter_by(
            name=i
        ).first()
        if biz:
            item = session.query(Product).filter_by(
                name=biz.latest
            ).first()
            if item:
                result.append(item)
                biz.latest = None
                session.commit()
    if len(result) > 0:
        for i in result:
            update.callback_query.message.reply_photo(
                photo=i.image,
                caption=f"{i.sme.name}\n=========\n{i.name} \nDescription: {i.description}\nPrice:{i.price}"
            )
    else:
        update.callback_query.message.reply_text(
            "No new updates"
        )
    time.sleep(86400)
    return getupdates(update, context)

def smecat(update, context):
    # create business
    data = update.message.text.split(',')
    if len(data) < 4 or len(data) > 4:
        button = [
            [InlineKeyboardButton(
                text="Continue..",
                callback_data="sme"
            )]
        ]
        update.message.reply_text(
            "Invalid entry, please make sure to input the details "
            "as requested in the instructions",
            reply_markup=InlineKeyboardMarkup(button)
        )
        return CHOOSING
    else:
        newbiz = Business(
            name=data[0], email=data[1],
            address=data[2], telephone=data[3],
            owner=owner
        )
        # TODO: Add checks for correct len of input data
        session.add(newbiz)
        try:
            session.commit()
        except IntegrityError:
            session.rollback()
            print("Duplicate data")
            update.message.reply_text(
                "Business with email already exists, try again"
            )
            return CHOOSESME_CAT
        categories = [
            ['Clothing/Fashion', 'Hardware Accessories'],
            ['Food/Kitchen Ware', 'ArtnDesign'],
            ['Other']
        ]
        markup = ReplyKeyboardMarkup(categories, one_time_keyboard=True)
        update.message.reply_text(
            "Pick a category for your business from the options",
            reply_markup=markup
        )
        return ADD_PRODUCTS

def products(update, context):
    biz = owner.sme
    cat_ = session.query(Category).filter_by(name=update.message.text).first()
    biz.category = cat_
    session.commit()
    button = [[
        InlineKeyboardButton(
            text="Add a product",
            callback_data=biz.category.name
        )
    ]]
    update.message.reply_text(
        "Lets add some of your products - shall we>, 🛍",
        reply_markup=InlineKeyboardMarkup(button)
    )
    return ADD_PRODUCTS

def addproduct(update, context):
    choice = update.callback_query.data
    print(choice)
    update.callback_query.message.reply_text(
        "Add the Name, Description, and Price of product, "
        "separated by commas(,) as caption to the product's image"
    )
    return ADD_PRODUCTS

def product_info(update: Update, context: CallbackContext):
    data = update.message
    print(data)
    photo = context.bot.getFile(update.message.photo[-1].file_id)
    file_ = open('product_image', 'wb')
    photo.download(out=file_)
    data = update.message.caption.split(',')
    # upload image to cloudinary
    send_photo = upload('product_image', width=200, height=150, crop='thumb')
    # create new product
    newprod = Product(
        name=data[0], description=data[1],
        price=data[2], image=send_photo['secure_url'],
        sme=owner.sme
    )
    session.add(newprod)
    owner.sme.latest = newprod.name
    session.commit()
    button = [[InlineKeyboardButton(
        text='Add another product',
        callback_data=owner.sme.category.name
    )]]
    update.message.reply_text(
        "Added product successfully",
        reply_markup=InlineKeyboardMarkup(button)
    )
    return ADD_PRODUCTS

def cancel(update: Update, context: CallbackContext) -> int:
    update.message.reply_text(
        'Bye! I hope we can talk again some day.',
        reply_markup=ReplyKeyboardRemove()
    )

    return ConversationHandler.END

def main():
    conv_handler = ConversationHandler(
        entry_points=[
            CommandHandler('start', start)
        ],
        states={
            CLASS_STATE: [
                MessageHandler(
                    Filters.all, classer
                )
            ],
            CHOOSING: [
                # MessageHandler(
                #     Filters.regex(r'^(SME|sme|Sme)$'), smedetails
                # ),
                # MessageHandler(
                #     Filters.regex(r'(^Customer|customer|CUSTOMER)$'),
                #     customer_details
                # )
                CallbackQueryHandler(
                    customer_details
                )
            ],
            FETCH_PREFERENCES: [
                CallbackQueryHandler(
                    fetch_preference
                )
            ],
            ADD_PRODUCTS: [
                MessageHandler(
                    Filters.regex(r'^(Clothing/Fashion|Hardware Accessories|Food/Kitchen Ware|ArtnDesign)$'),
                    products
                ),
                MessageHandler(
                    Filters.all,
                    product_info
                ),
                CallbackQueryHandler(
                    addproduct
                )
            ],
            FETCH_SUBPREFERENCE: [
                CallbackQueryHandler(
                    fetch_bizpref
                )
            ],
            CHOOSESME_CAT: [
                MessageHandler(
                    Filters.all,
                    smecat
                )
            ],
            FETCH_SMECONTACT: [
                CallbackQueryHandler(
                    smecontact
                )
            ],
            FETCH_UPDATES: [
                CallbackQueryHandler(
                    getupdates
                )
            ]
        },
        fallbacks=[CommandHandler('cancel', cancel)],
        allow_reentry=True
    )
    dispatcher.add_handler(conv_handler)
    updater.start_polling()
    updater.idle()

if __name__ == "__main__":
    main()


import os
import sys
import argparse
import logging
import subprocess
import glob

FORMAT = "%(asctime)-15s: %(message)s"
logging.basicConfig(format=FORMAT)
logger = logging.getLogger()
logger.setLevel(logging.INFO)

MODEL_NAME_MAP = {
    "bert-small": "bert-small-cased",
    }

parser = argparse.ArgumentParser()
parser.add_argument("--res_path_pat", type=str, default="./cache/train_s-cls_cloud/*", help="")
parser.add_argument("--task", type=str, help="")
parser.add_argument("--task_type", type=str, help="s-cls, seq-tag")
parser.add_argument("--run_date", type=str, help="")
parser.add_argument("--langs", type=str, help="test languages")
parser.add_argument("--out_dir", type=str, help="")
parser.add_argument("--data_dir", type=str, help="")
parser.add_argument("--model_name", type=str, help="")
args = parser.parse_args()

def main():
  res_paths = glob.glob(args.res_path_pat)
  task = args.task

  run_date = args.run_date
  exec_script = f"scripts/test_{args.task_type}_cloud.sh"
  exec_script_name = os.path.basename(exec_script)

  out_dir = os.path.join(args.out_dir, exec_script_name)
  os.makedirs(out_dir, exist_ok=True)

  for i, path in enumerate(res_paths):
    fields = path.split('/')
    model_name, langs, spec_dir = fields[-5], fields[-3], fields[-1]
    tgt_langs = args.langs
    if args.model_name:
      model_name = args.model_name
    else:
      model_name = MODEL_NAME_MAP[model_name] if model_name in MODEL_NAME_MAP else model_name
    # print(model_name, tgt_lang, spec_dir)
    log_prefix = os.path.join(out_dir, f"{run_date}.none.{model_name}.{tgt_langs}")
    cmd = f"{exec_script} --test_langs={tgt_langs} --model={model_name} --data_dir={args.data_dir} --load_dir={path}/checkpoint-best/ --task={task}"
    logger.info(" ###### running")
    logger.info(cmd)
    with open(log_prefix + ".info", 'w') as finfo, open(log_prefix + ".err", 'w') as ferr:
      results = subprocess.run([sys.executable] + cmd.split(' '), stdout=finfo, stderr=ferr) # py3.7+: , capture_output=True, text=True)
    logger.info(f" ###### results: {results}")

if __name__ == "__main__":
  main()


from nltk.tag import StanfordPOSTagger
from nltk.tokenize import word_tokenize
import re
import os

from path_reader import PathReader

pathreader = PathReader("./PATHS")

os.environ['CLASSPATH'] = pathreader.get_path('TAGGER')
os.environ['STANFORD_MODELS'] = pathreader.get_path('TAGGER') + "/models"

class FeatureProcessing(object):
  def __init__(self):
    self.feat_index = {}
    self.implication_words = ["demonstrate", "suggest", "indicate"]
    self.hyp_words = ["possible"]
    self.method_words = ["probe", "detect"]
    self.pos_tagger = StanfordPOSTagger('english-bidirectional-distsim.tagger')

  def get_features(self, phrase, filter_feature='0'):
    words = word_tokenize(phrase)
    pos_tags = self.pos_tagger.tag(words)
    features = []
    for word, tag in pos_tags:
      wl = word.lower()
      # Feat 1: POS features
      if filter_feature != '1':
        if tag != ',' and tag != '.':
          features.append(tag)
      # Feat 2: Verb and adverb identity
      if filter_feature != '2':
        if tag == 'RB' or tag.startswith('VB'):
          features.append(wl)
      # Feat 3: Presence of figure references and citations
      if filter_feature != '3':
        if word.startswith("Fig"):
          features.append("figure")
        if re.search("[A-Z][^\s]+ et al.", phrase) is not None:
          features.append("reference")
    # Feat 4: Presence of specific words or phrases
    if filter_feature != '4':
      if re.search("[Dd]ata not shown", phrase) is not None:
        features.append("data_not_shown")
      for word in self.implication_words:
        if word in phrase:
          features.append("implication_word")
      for word in self.hyp_words:
        if word in phrase:
          features.append("hyp_word")
      for word in self.method_words:
        if word in phrase:
          features.append("method_word")
    return features

  def index_data(self, data, filter_feature='0'):
    all_features = [self.get_features(datum, filter_feature) for datum in data]
    for features in all_features:
      for feat in features:
        if feat not in self.feat_index:
          self.feat_index[feat] = len(self.feat_index)

  def featurize(self, phrase, filter_feature='0'):
    indexed_features = [0] * len(self.feat_index)
    features = self.get_features(phrase, filter_feature)
    for feat in features:
      if feat not in self.feat_index:
        continue
      indexed_features[self.feat_index[feat]] += 1
    return indexed_features


from django.core.management.base import BaseCommand
from usaspending_api.references.models import Cfda
from datetime import datetime
import os
import csv
import logging
import django
import ftplib

logger = logging.getLogger('console')
cfda_relative_path = '/usaspending_api/references/management/commands/programs-full-usaspending.csv'
cfda_abs_path = os.path.join(django.conf.settings.BASE_DIR + cfda_relative_path)

class Command(BaseCommand):

    help = 'Loads program information obtained from csv file on ftp.cfda.gov'

    def add_arguments(self, parser):
        parser.add_argument(
            '--update-file',
            action='store_true',
            dest='update-file',
            default=False,
            help='Pull the updated CSV from ftp.cfda.gov before running.'
        )

    def handle(self, *args, **options):

        if options['update-file']:

            ftp_conn = ftplib.FTP()
            ftp_conn.connect("ftp.cfda.gov")
            ftp_conn.login()
            ftp_conn.cwd('usaspending')
            most_recent = sorted(ftp_conn.nlst(), reverse=True)[0]

            logger.info('Updating {} with new file {}...'.format(cfda_abs_path, most_recent))
            ftp_conn.retrbinary("RETR " + most_recent, open(cfda_abs_path, 'wb').write)

        load_cfda(cfda_abs_path)

def load_cfda(abs_path):
    """
    Using file at abs_path, update/create CFDA objects.
    """
    try:

        with open(abs_path, errors='backslashreplace') as csvfile:

            reader = csv.DictReader(csvfile, delimiter=',', quotechar='"', skipinitialspace='true')

            rows = list(reader)
            total_rows = len(rows)

            for index, row in enumerate(rows, 1):

                if not (index % 100):
                    logger.info('CFDA loading/updating row {} of {}'.format(index, total_rows))

                cfda_program, created = Cfda.objects.get_or_create(
                                program_number=row['Program Number'])

                cfda_program.data_source = "USA"
                cfda_program.program_title = row['Program Title']
                cfda_program.popular_name = row['Popular Name (020)']
                cfda_program.federal_agency = row['Federal Agency (030)']
                cfda_program.authorization = row['Authorization (040)']
                cfda_program.objectives = row['Objectives (050)']
                cfda_program.types_of_assistance = row['Types of Assistance (060)']
                cfda_program.uses_and_use_restrictions = row['Uses and Use Restrictions (070)']
                cfda_program.applicant_eligibility = row['Applicant Eligibility (081)']
                cfda_program.beneficiary_eligibility = row['Beneficiary Eligibility (082)']
                cfda_program.credentials_documentation = row['Credentials/Documentation (083)']
                cfda_program.pre_application_coordination = row['Preapplication Coordination (091)']
                cfda_program.application_procedures = row['Application Procedures (092)']
                cfda_program.award_procedure = row['Award Procedure (093)']
                cfda_program.deadlines = row['Deadlines (094)']
                cfda_program.range_of_approval_disapproval_time = row['Range of Approval/Disapproval Time (095)']
                cfda_program.appeals = row['Appeals (096)']
                cfda_program.renewals = row['Renewals (097)']
                cfda_program.formula_and_matching_requirements = row['Formula and Matching Requirements (101)']
                cfda_program.length_and_time_phasing_of_assistance = row['Length and Time Phasing of Assistance (102)']
                cfda_program.reports = row['Reports (111)']
                cfda_program.audits = row['Audits (112)']
                cfda_program.records = row['Records (113)']
                cfda_program.account_identification = row['Account Identification (121)']
                cfda_program.obligations = row['Obligations (122)']
                cfda_program.range_and_average_of_financial_assistance = row['Range and Average of '
                                                                             'Financial Assistance (123)']
                cfda_program.program_accomplishments = row['Program Accomplishments (130)']
                cfda_program.regulations_guidelines_and_literature = row['Regulations, Guidelines, '
                                                                         'and Literature (140)']
                cfda_program.regional_or_local_office = row['Regional or Local Office (151) ']
                cfda_program.headquarters_office = row['Headquarters Office (152)']
                cfda_program.website_address = row['Website Address (153)']
                cfda_program.related_programs = row['Related Programs (160)']
                cfda_program.examples_of_funded_projects = row['Examples of Funded Projects (170)']
                cfda_program.criteria_for_selecting_proposals = row['Criteria for Selecting Proposals (180)']
                cfda_program.url = row['URL']
                cfda_program.recovery = row['Recovery']
                cfda_program.omb_agency_code = row['OMB Agency Code']
                cfda_program.omb_bureau_code = row['OMB Bureau Code']
                if row['Published Date']:
                    cfda_program.published_date = datetime.strptime(row['Published Date'], '%b, %d %Y')
                if row['Archived Date']:
                    cfda_program.archived_date = datetime.strptime(row['Archived Date'], '%b, %d %Y')

                # TODO: add way to check/print out any cfda codes that got updated (not just created)
                if created:
                    logger.info('Created a new cfda code for {} ({})'.format(row['Program Number'],
                                                                             row['Program Title']))

                cfda_program.save()

    except IOError:
        logger.info('Could not open file to load: {}'.format(abs_path))


import unittest

def soundex(name, len=4):
    """ soundex module conforming to Knuth's algorithm
        implementation 2000-12-24 by Gregory Jorgensen
        public domain
    """

    # digits holds the soundex values for the alphabet
    digits = '01230120022455012623010202'
    sndx = ''
    fc = ''

    # translate alpha chars in name to soundex digits
    for c in name.upper():
        if c.isalpha():
            if not fc: fc = c   # remember first letter
            d = digits[ord(c)-ord('A')]
            # duplicate consecutive soundex digits are skipped
            if not sndx or (d != sndx[-1]):
                sndx += d

    # replace first digit with first alpha character
    sndx = fc + sndx[1:]

    # remove all 0s from the soundex code
    sndx = sndx.replace('0','')

    # return soundex code padded to len characters
    return (sndx + (len * '0'))[:len]

class SoundexTester(unittest.TestCase):

    def test_soundex_of_simple_names(self):
        self.assertEquals(soundex("john"),soundex("jhon"))
        self.assertEquals(soundex("mary"),soundex("mairie"))
        self.assertEquals(soundex("stefan"),soundex("steven"))
        self.assertNotEqual(soundex("steve"),soundex("stacy"))


# Creates intersection of input domain ranges with observed residues from PDBe API. Input and output is in JSON format { pdb: [[domain_name, chain, range]] }.

import sys
from pathlib import Path
import requests
import json
import argparse
from typing import List, Tuple, Dict
from collections import defaultdict

#  PARSE ARGUMENTS  ################################################################################

DEFAULT_API_URL = 'https://www.ebi.ac.uk/pdbe/api/pdb/entry/polymer_coverage'

parser = argparse.ArgumentParser()
parser.add_argument('input_domains', help='JSON file with input domains in format { pdb: [[domain_name, chain, range]] }', type=Path)
parser.add_argument('--source', help='URL with PDBeAPI server for Observed residues (default = ' + DEFAULT_API_URL + ')', default=DEFAULT_API_URL)
parser.add_argument('--min_residues', help='Remove domains with less than this number of residues (default: 0)', type=int, default=0)
args = parser.parse_args()

input_domains_file = args.input_domains
api_url = args.source
min_residues = args.min_residues

#  FUNCTIONS  ################################################################################

def parse_ranges(ranges: str) -> List[Tuple[int,int]]:
    """Parse domain ranges, e.g. '1:100,150:200' -> [(1,100), (150,200)]"""
    result = []
    for rang in ranges.split(','):
        start, end = rang.split(':')
        start = int(start) if start != '' else float('-inf')
        end = int(end) if end != '' else float('+inf')
        result.append((start, end))
    return result

def format_ranges(ranges: List[Tuple[int,int]]) -> str:
    """Format domain ranges, e.g. [(1,100), (150,200)] -> '1:100,150:200'"""
    return ','.join(f'{r[0]}:{r[1]}' for r in ranges)

def get_observed_residues(pdb: str, source_api_url: str) -> Dict[str, List[Tuple[int,int]]]:
    url = f'{source_api_url}/{pdb}'
    response = requests.get(url)
    info = json.loads(response.text)
    molecules = info[pdb]['molecules']
    result = {}
    for molecule in molecules:
        for chain in molecule['chains']:
            chain_id = chain['struct_asym_id']
            ranges_in_chain = []
            for rang in chain['observed']:
                start = rang['start']['residue_number']
                end = rang['end']['residue_number']
                ranges_in_chain.append((start, end))
            ranges_in_chain.sort()
            assert chain_id not in result
            result[chain_id] = ranges_in_chain
    return result

def consolidate_ranges(ranges: List[Tuple[int,int]]) -> List[Tuple[int,int]]:
    """Return equivalent set of ranges, which is without overlaps and sorted, e.g. [(120,155), (1,100), (150,200)] -> [(1,100), (120,200)]"""
    stack = sorted(ranges, reverse=True)
    result = []
    while len(stack) >= 2:
        head = stack[-1]
        neck = stack[-2]
        if neck[0] <= head[1] + 1:
            union = (head[0], max(head[1], neck[1]))
            stack.pop()
            stack.pop()
            stack.append(union)
        else:
            stack.pop()
            result.append(head)
    result.extend(stack)
    return result

def ranges_intersection(ranges1: List[Tuple[int,int]], ranges2: List[Tuple[int,int]]) -> List[Tuple[int,int]]:
    """Return the intersection of two sets of ranges, e.g. [(1,100), (150,200)] + [(50,180)] -> [(50,100), (150,180)]"""
    stack1 = sorted(consolidate_ranges(ranges1), reverse=True)
    stack2 = sorted(consolidate_ranges(ranges2), reverse=True)
    result = []
    while len(stack1) > 0 and len(stack2) > 0:
        head1 = stack1[-1]
        head2 = stack2[-1]
        overlap_start = max(head1[0], head2[0])
        overlap_end = min(head1[1], head2[1])
        if overlap_start <= overlap_end:
            result.append((overlap_start, overlap_end))
        if head1[1] < head2[1]:
            stack1.pop()
        else:
            stack2.pop()
    return result

def ranges_residue_count(ranges: List[Tuple[int,int]]) -> int:
    """Return total number of residues in domain ranges, e.g. [(1,100), (150,200)] -> 151"""
    return sum(r[1] - r[0] + 1 for r in ranges)

#  MAIN  ###############################################################################

with open(input_domains_file) as f:
    pdb2domains = json.load(f)

result = defaultdict(list)

print(f'Input: {sum(len(doms) for doms in pdb2domains.values())} domains in {len(pdb2domains)} PDB entries', file=sys.stderr)

for pdb, domains in pdb2domains.items():
    observed = get_observed_residues(pdb, api_url)
    # print(pdb, observed)
    for domain_name, chain, ranges in domains:
        domain_ranges = parse_ranges(ranges)
        observed_ranges = observed.get(chain, [])
        overlap = ranges_intersection(domain_ranges, observed_ranges)
        print(ranges_residue_count(overlap), pdb, chain, format_ranges(domain_ranges), format_ranges(observed_ranges), format_ranges(overlap), file=sys.stderr)
        if ranges_residue_count(overlap) >= min_residues:
            new_domain = (domain_name, chain, format_ranges(overlap))
            result[pdb].append(new_domain)
            # print(f'    {chain}: {domain_ranges}  {overlap}')
        else:
            pass
            # print(f'Removing  domain: {pdb} {chain} {format_ranges(domain_ranges)} (observed: {format_ranges(observed_ranges)})', file=sys.stderr)

json.dump(result, sys.stdout, indent=4)

print(f'Output: {sum(len(doms) for doms in result.values())} domains in {len(result)} PDB entries', file=sys.stderr)

# url = api_url + '/' + accession
# sys.stderr.write('Downloading ' + url + '\n')
# response = requests.get(url)
# if response.ok:
#     results = json.loads(response.text).get(accession, {}).get('PDB', {})
# else:
#     sys.stderr.write('HTTP request failed, status code ' + str(response.status_code) + '.\n')
#     exit(1)

# output = {}
# for pdb, entry in results.items():
#     if isinstance(entry, list):
#         output[pdb] = get_domains_multisegment(entry, pdb)
#     elif isinstance(entry, dict) and 'mappings' in entry:
#         output[pdb] = get_domains_multisegment(entry['mappings'], pdb)

# n_pdbs = len(output)
# n_domains = sum( len(doms) for pdb, doms in output.items() )

# sys.stderr.write(f'Found {n_domains} domains in {n_pdbs} PDB entries.\n')

# print(json.dumps(output, sort_keys=True, indent=4))


#https://leetcode.com/problems/coin-change/

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        #DP
        #f[j] = min(f[j], f[j-ci] + 1) 总价值j
        #f[0] = 0
        f = [float('inf')] * (amount + 1)
        f[0] = 0
        for c in coins:
            for j in range(c, amount+1):
                f[j] = min(f[j], f[j - c] + 1)
        return f[amount] if f[amount]!=float('inf') else -1