import typing

import discord
from discord.ext import commands

from .general import is_staff, free_category, free_category_create

class FreeCategory(commands.Cog):
    __slots__ = ('client', 'name', 'staff',)
    permissions_jp = {
        # 'create_instant_invite': '招待を作成',
        'manage_channels': 'チャンネルの管理',
        'manage_roles': '権限の管理',
    }
    permissions_jp_text = {
        'read_messages': 'メッセージを読む',
        'send_messages': 'メッセージを送信',
        'manage_messages': 'メッセージの管理',
        'embed_links': '埋め込みリンク',
        'attach_files': 'ファイルを添付',
        'read_message_history': 'メッセージ履歴を読む',
        'external_emojis': '外部の絵文字の使用',
        'add_reactions': 'リアクションの追加',
    }
    permissions_jp_voice = {
        'read_messages': 'チャンネルを見る',
        'connect': '接続',
        'speak': '発言',
        'mute_members': 'メンバーをミュート',
        'deafen_members': 'メンバーのスピーカーをミュート',
        'move_members': 'メンバーを移動',
        'use_voice_activation': '音声検出を使用',
        'priority_speaker': 'プライオリティスピーカー'
    }

    def __init__(self, client, name=None,):
        self.client: commands.Bot = client
        self.name = name if name is not None else type(self).__name__

    @property
    def category(self):
        return self.client.get_channel(free_category)

    @property
    def create_channel(self):
        return self.client.get_channel(free_category_create)

    @commands.command(name='ftcc')
    async def free_text_channel_create(self, ctx, *, name):
        channel = await self._free_channel_create(ctx, name)
        if channel is not None:
            await ctx.send(
                '作成しました。\n{0}\nあと{1}チャンネル作成可能。'
                .format(channel.mention, 50 - len(channel.category.channels))
            )

    async def _free_channel_create(self, ctx, name):
        category = self.category
        if len(category.channels) >= 50:
            await ctx.send(
                "チャンネルが一杯で作成できません。\n"
                "運営に連絡してください。"
            )
            return
        guild = category.guild
        overwrites = {
            self.client.user:
                discord.PermissionOverwrite.from_pair(discord.Permissions.all(), discord.Permissions.none()),
            ctx.author:
                discord.PermissionOverwrite.from_pair(discord.Permissions(66448721), discord.Permissions.none()),
            guild.default_role:
                discord.PermissionOverwrite.from_pair(discord.Permissions.none(), discord.Permissions.all()),
            guild.get_role(515467411898761216):
                discord.PermissionOverwrite.from_pair(discord.Permissions.none(), discord.Permissions.all()),
            guild.get_role(515467425429585941):
                discord.PermissionOverwrite.from_pair(
                    discord.Permissions(37080128), discord.Permissions(2 ** 53 - 37080129)),
        }
        return await guild.create_text_channel(name, overwrites=overwrites, category=category)

    @commands.command()
    async def cedit(self, ctx,
                    channel: typing.Union[discord.TextChannel, discord.VoiceChannel] = None):
        EMOJI = 0x1f1e6  # 絵文字定数(これを足したり引いたりするとリアクション的にうまくいく)
        EMBED_TITLE = 'チャンネル権限編集'
        if channel is None:
            channel = ctx.channel
        if (
            (
                ctx.author in channel.overwrites
                and channel.overwrites_for(ctx.author).manage_roles is not False
            )  # メンバーの追加設定があり、かつ「権限の管理」がNone
            or await self.client.is_owner(ctx.author)  # オーナー
            or await is_staff(ctx.author)  # スタッフチーム
        ):
            all_commands = (
                '新規に役職を追加設定',
                '新規にユーザーを追加設定',
                '現在設定されている追加設定の変更',
                '現在設定されている追加設定の削除'
            )
            emojis = [chr(i + EMOJI) for i in range(len(all_commands))]
            embed = discord.Embed(
                title=EMBED_TITLE,
                description='\n'.join(
                    '{0}:{1}'.format(i, e)
                    for i, e in zip(emojis, all_commands)
                )
            )
            embed.set_footer(text='対象チャンネル:{0.name}\nチャンネルID:{0.id}'.format(channel))
            message = await ctx.send(embed=embed)
            [await message.add_reaction(e)
             for e in emojis]

            def check(r, u):
                return (
                        r.me and ctx.author == u
                        and r.message.id == message.id
                        and r.message.channel == message.channel
                )
            reaction, _ = \
                await self.client.wait_for('reaction_add', check=check)
            await message.delete()
            num_command = ord(reaction.emoji) - EMOJI
            if 0 <= num_command <= 1:
                # ユーザーまたは役職の追加
                if num_command == 0:
                    target_type = '役職'
                else:
                    target_type = 'ユーザー'
                description1 = ('チャンネルの追加設定に{0}を追加します。\n'
                               '追加したい{0}を入力してください').format(target_type)
                message = await ctx.send(description1)

                def check1(m):
                    return (
                            m.channel == ctx.channel
                            and m.author == ctx.author
                    )
                message2 = await self.client.wait_for('message', check=check1)
                await message.delete()
                if num_command == 0:
                    converter = commands.RoleConverter()
                else:
                    converter = commands.MemberConverter()
                try:
                    target = await converter.convert(ctx, message2.content)
                except commands.BadArgument:
                    await ctx.send(
                        '指定した{0}が見つかりませんでした'.format(target_type)
                        + 'もう一度やり直して下さい。'
                    )
                    return
            elif 2 <= num_command <= 3:
                action = '変更' if num_command == 2 else '削除'
                description1 = (
                    '追加設定を{0}します\n'
                    '{0}したい役職、またはユーザーを選んでください'
                ).format(action)
                embed = discord.Embed(title=EMBED_TITLE, description=description1)
                overwrites = channel.overwrites

                def func2(_page=0):
                    end = (_page + 1) * 17
                    if len(overwrites) < end:
                        end = len(overwrites)
                    start = _page * 17
                    tg = [i for i in overwrites.keys()][start:end]
                    try:
                        tg.remove(self.client.user)
                    except ValueError:
                        pass
                    desc = '\n'.join(
                        '{0}:{1}'.format(chr(i + EMOJI), t.mention)
                        for i, t in enumerate(tg)
                    )
                    return tg, desc
                page = 0
                targets, description1 = func2(page)
                embed.add_field(name='役職・ユーザー一覧', value=description1)
                message = await ctx.send(embed=embed)
                [await message.add_reaction(chr(i + EMOJI))
                 for i in range(len(targets))]
                await message.add_reaction('\U0001f519')
                await message.add_reaction('\U0001f51c')
                await message.add_reaction('\u274c')

                def check3(r, u):
                    return (
                            u == ctx.author
                            and r.me
                            and r.message.channel == message.channel
                            and r.message.id == message.id
                    )

                while True:
                    new_page = page
                    reaction, user = \
                        await self.client.wait_for('reaction_add', check=check3)
                    await message.remove_reaction(reaction, user)
                    if reaction.emoji == '\U0001f519':
                        new_page = page - 1
                    elif reaction.emoji == '\U0001f51c':
                        new_page = page + 1
                    elif reaction.emoji == '\u274c':
                        await message.delete()
                        await ctx.send('中止しました。')
                        return
                    else:
                        break
                    if new_page != page:
                        new_targets, description1 = func2(_page=new_page)
                        if description1 != '':
                            embed.set_field_at(
                                0, name='役職・ユーザー一覧', value=description1
                            )
                            await message.edit(embed=embed)
                            page = new_page
                            targets = new_targets
                await message.delete()
                target = targets[ord(reaction.emoji) - EMOJI]
            if num_command <= 2:
                perms_jp = self.permissions_jp.copy()
                perms_jp.update(
                    self.permissions_jp_text
                    if isinstance(channel, discord.TextChannel)
                    else self.permissions_jp_voice
                )
                perms = tuple(perms_jp.keys())

                def func1(overwrite):
                    description = ''
                    n = 0
                    for en, jp in perms_jp.items():
                        try:
                            value = getattr(overwrite, en)
                        except AttributeError:
                            continue
                        else:
                            description += '{0}'.format(chr(n + EMOJI))
                            description += jp
                        if value:
                            description += ':\u2705\n'
                        elif value is None:
                            description += ':\u2b1c\n'
                        else:
                            description += ':\u274c\n'
                        n += 1
                    return description
                overwrite1: discord.PermissionOverwrite = channel.overwrites_for(target)
                embed = discord.Embed(
                    title=EMBED_TITLE,
                    description='{0}の権限設定を変更します'.format(target.mention)
                )
                embed.add_field(name='権限一覧', value=func1(overwrite1))
                message3 = await ctx.send(embed=embed)
                [await message3.add_reaction(chr(i + EMOJI))
                 for i in range(len(perms))]
                await message3.add_reaction('\u2705')
                await message3.add_reaction('\u274c')

                def check2(reaction, user):
                    return (
                        user == ctx.author
                        and reaction.me
                        and reaction.message.channel == message3.channel
                        and reaction.message.id == message3.id
                    )

                loop = True
                while loop:
                    reaction, user = await self.client.wait_for('reaction_add', check=check2)
                    if reaction.emoji == '\u2705':
                        loop = False
                        continue
                    elif reaction.emoji == '\u274c':
                        await message3.delete()
                        await ctx.send('中止しました。')
                        break
                    await message3.remove_reaction(reaction, user)
                    perm = perms[ord(reaction.emoji) - EMOJI]
                    value = getattr(overwrite1, perm)
                    if value:
                        value = False
                    elif value is None:
                        value = True
                    else:
                        value = None
                    if perm == 'manage_roles' and value:
                        value = False
                    overwrite1.update(**{perm: value})
                    embed.set_field_at(0, name='権限一覧', value=func1(overwrite1))
                    await message3.edit(embed=embed)
                else:
                    await message3.delete()
                    await channel.set_permissions(target, overwrite=overwrite1)
                    await ctx.send('権限を変更しました。')
            elif num_command == 3:
                await channel.set_permissions(target, overwrite=None)
                await ctx.send('権限を削除しました。')
        else:
            await ctx.send('あなたはそれをする権限がありません。')


import os
import sys
import numpy as np
import matplotlib.pyplot as plt
import getdist
#from getdist import plots, MCSamples

sys.path.append(
    "{}/utils".format(os.environ["GitHub"])
)
import list_utils as list_utils
import directory_utils as directory_utils

# NOTE: A LOT NEED TO CHANGE HERE ...
# TODO: The samples in the 2dmarginal plot need not be in a grid.

def get_list_of_directory_trees_in_directory(directory):
    return [
        x[0]
        for x in os.walk(directory)
    ]

def get_subphase_directory(x_i, x_j, y_i, y_j):

    str_0 = "galaxies_subhalo_mass_centre_0_" + "{0:.2f}".format(x_i) + "_" + "{0:.2f}".format(x_j)
    str_1 = "galaxies_subhalo_mass_centre_1_" + "{0:.2f}".format(y_i) + "_" + "{0:.2f}".format(y_j)

    return "{}_{}".format(
        str_0,
        str_1
    )

def get_subphase_directories_for_gridsearch(phase_directory, xmin, xmax, ymin, ymax, number_of_steps):

    x = np.linspace(xmin, xmax, number_of_steps + 1)
    y = np.linspace(ymin, ymax, number_of_steps + 1)

    directories = []
    for i in range(number_of_steps):
        directories_temp = []
        for j in range(number_of_steps):
            subphase_directory = get_subphase_directory(
                x_i=x[i], x_j=x[i+1], y_i=y[j], y_j=y[j+1]
            )

            # TODO: sanitize the phase directory
            phase_directory = directory_utils.sanitize_directory(
                directory=phase_directory
            )
            subphase_directory = phase_directory + "/" + subphase_directory
            if not os.path.isdir(subphase_directory):
                raise IOError(subphase_directory + " does not exist")

            list_of_directory_trees_filtered = list_utils.filter_input_list_of_strings_after_split_with_ending_string(
                input_list_of_strings=get_list_of_directory_trees_in_directory(
                    directory=subphase_directory
                ),
                split_character="/",
                ending_string="optimizer_backup"
            )

            if len(list_of_directory_trees_filtered) == 1:
                if not os.listdir(list_of_directory_trees_filtered[0]):
                    directories_temp.append(None)
                else:
                    directories_temp.append(list_of_directory_trees_filtered[0])
            if len(list_of_directory_trees_filtered) < 1:
                directories_temp.append(None)
                #raise ValueError("optimizer_backup does not exist")
            if len(list_of_directory_trees_filtered) > 1:
                raise ValueError("THIS IS WEIRD...")

        directories.append(directories_temp)

    return directories

def get_samples_from_subphase_directories(directories):

    samples = []
    for i in range(np.shape(directories)[0]):
        samples_temp = []
        for j in range(np.shape(directories)[1]):
            if directories[i][j] is not None:
                directory = directories[i][j] + "/multinest"
                try:
                    sample = getdist.mcsamples.loadMCSamples(directory)
                    #print(sample.__dict__)
                except:
                    sample = None
            else:
                sample = None

            samples_temp.append(sample)

        samples.append(samples_temp)

    return samples

def subhalo_grid_plot_from_samples(samples, levels=None):

    plt.figure(
        figsize=(15, 15)
    )

    # ...
    if levels is None:
        levels = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

    # ...
    for i in range(np.shape(samples)[0]):
        for j in range(np.shape(samples)[0]):
            sample_temp = samples[i][j]
            if sample_temp is not None:

                density2D = sample_temp.get2DDensity(
                    'galaxies_subhalo_mass_centre_1',
                    'galaxies_subhalo_mass_centre_0'
                )

                if density2D is not None:
                    plt.contour(
                        density2D.x,
                        density2D.y,
                        density2D.P,
                        levels=levels,
                        colors="black"
                    )
                    #print("OK")

    for i in np.linspace(-2.0, 2.0, 5):
        plt.axvline(i, linestyle="--", linewidth=2, color="r")
        plt.axhline(i, linestyle="--", linewidth=2, color="r")

    plt.plot([-1.0], [0.0], marker="*", markersize=20, color="b")

    plt.xlabel("x (arcsec)", fontsize=20)
    plt.ylabel("y (arcsec)", fontsize=20)
    plt.xlim((-2.1, 2.1))
    plt.ylim((-2.1, 2.1))
    plt.show()

if __name__ == "__main__":

    phase_directory = "/Users/ccbh87/Desktop/COSMA/cosma7/data/dp004/dc-amvr1/workspace/output/interferometer/lens_powerlaw_and_shear_and_subhalo__source_ellipticalcoresersic/model_1/total_flux_1.0_Jy/5.6/230GHz/t_tot__60s/t_int__10s/n_channels_128/0.5mm/width_128/pipeline__lens_fixed_with_subhalo__source_inversion/general/source__pix_voro_mag__reg_const__with_shear/phase_2__subhalo_search__source/phase_tag__rs_shape_125x125__rs_pix_0.04x0.04__sub_2__pos_0.20/"
    xmin = -2.0
    xmax = 2.0
    ymin = -2.0
    ymax = 2.0
    number_of_steps = 4

    subphase_directories = get_subphase_directories_for_gridsearch(
        phase_directory=phase_directory,
        xmin=xmin,
        xmax=xmax,
        ymin=ymin,
        ymax=ymax,
        number_of_steps=number_of_steps
    )

    samples = get_samples_from_subphase_directories(directories=subphase_directories)

    subhalo_grid_plot_from_samples(samples=samples)


# Opus/UrbanSim urban simulation software.
# Copyright (C) 2010-2011 University of California, Berkeley, 2005-2009 University of Washington
# See opus_core/LICENSE

from numpy import float32, arcsin, sqrt
from numpy import ma
from opus_core.variables.variable import Variable
from biocomplexity.land_cover.variable_functions import my_attribute_label

class pwa(Variable):
    """Percent water within footprint.
      - need {"constants":{"FOOTPRINT":footprint,"OW":12}} in resources
          when compute, where footprint=ones(shape=(5,5), dtype="int32")."""
    land_cover_type_ow_within_footprint = 'land_cover_type_ow_within_footprint' # ow->open_water
    footprint_size = 'footprint_size'

    def dependencies(self):
        return [my_attribute_label(self.land_cover_type_ow_within_footprint),
                my_attribute_label(self.footprint_size)]

    def compute(self, dataset_pool):
        den = self.get_dataset().get_attribute(self.footprint_size).astype(float32)
        pct = self.get_dataset().get_attribute(self.land_cover_type_ow_within_footprint)
        return ma.filled(arcsin(sqrt(pct/den)), 0)

from numpy import array

from opus_core.tests import opus_unittest
from opus_core.datasets.dataset_pool import DatasetPool
from opus_core.storage_factory import StorageFactory

from biocomplexity.tests.expected_data_test import ExpectedDataTest

class Tests(ExpectedDataTest):
    variable_name = "biocomplexity.land_cover.pwa"

    def test_my_inputs(self):
        storage = StorageFactory().get_storage('dict_storage')

        storage.write_table(
            table_name='land_covers',
            table_data={
                'relative_x': array([1,2,1,2]),
                'relative_y': array([1,1,2,2]),
                "land_cover_type_ow_within_footprint": array([3, 2, 1, 0]),
                "footprint_size": array([5, 4, 5, 5])
            }
        )

        dataset_pool = DatasetPool(package_order=['biocomplexity'],
                                   storage=storage)
        footprint = array([[0,1,0], [1,1,1], [0,1,0]])
        dataset_pool._add_dataset(
            'constant',
            {
                "FOOTPRINT": footprint,
            }
        )

        gridcell = dataset_pool.get_dataset('land_cover')
        gridcell.compute_variables(self.variable_name,
                                   dataset_pool=dataset_pool)
        values = gridcell.get_attribute(self.variable_name)

        should_be = array([3, 2, 1, 0], dtype=float32) / array([5, 4, 5, 5], dtype=float32)
        should_be = arcsin(sqrt(should_be))

        self.assert_(ma.allclose( values, should_be, rtol=1e-7),
                     msg = "Error in " + self.variable_name)

    def test_on_expected_data(self):
        from numpy import ones
        footprint = ones(shape=(5,5), dtype="int32")
        self.do_test_on_expected_data(["lct","relative_x","relative_y"],
                                       {"constants":{"FOOTPRINT":footprint,"OW":12}},
                                      element_atol=0.07)

if __name__=='__main__':
    opus_unittest.main()


'''test_board.py - unit tests for board.py'''

# pylint: disable=E0401, W0621

from src.py import board
from src.py.player import Player
from src.py.card import Card

def test_get_player_name(monkeypatch):
    '''test get_player_name with mock inputs'''
    # Given
    inputs = iter(['Bryan', 'y'])
    monkeypatch.setattr('builtins.input', lambda _: next(inputs))

    # When
    name = board.get_player_name()

    # Then
    assert name == 'Bryan'

def test_pick_player(monkeypatch):
    '''test pick_player() with mock input'''
    # Given
    players = [Player('Hanna'), Player('Richard', bot=False), Player('Kate', bot=False)]
    monkeypatch.setattr('builtins.input', lambda _: 'Hanna')

    # When
    human_picked_player = board.pick_player(players[2], players)
    bot_picked_player   = board.pick_player(players[0], players)

    # Then
    assert human_picked_player.name() == 'Hanna'
    assert human_picked_player.bot()
    assert bot_picked_player.name() in ['Richard', 'Kate']
    assert not bot_picked_player.bot()

def test_pick_card_with_bot():
    '''test pick_card with bot arg'''
    # Given
    bot = Player('TEST BOT', True)
    bot.d_hand = [ Card('♠','A'), Card('♠','A'), Card('♠','A') ]

    # When
    picked_card = board.pick_card(bot)

    # Then
    assert picked_card.face()  == 'A'
    assert picked_card.suit()  == '♠'
    assert picked_card.space() == ' '

def test_pick_card_with_human(monkeypatch):
    '''test pick_card with human player & mock inputs'''
    # Given
    human = Player('TEST HUMAN', False)
    human.d_hand = [ Card('♡','Q'), Card('♡','K'), Card('♡','A') ]
    monkeypatch.setattr('builtins.input', lambda _: 'Q') # Mock user input

    # When
    picked_card = board.pick_card(human)

    # Then
    assert picked_card.face()  == 'Q'
    assert picked_card.suit()  == '♡'
    assert picked_card.space() == ' '


import os
import random
from captcha import image
import numpy as np
import PIL.Image as PILImage
import cv2
import shutil

def create_train_dataset(output_dir: str, width: float, height: float, captcha_count=4, count=2000):
    if not os.path.exists(output_dir):
        os.mkdir(output_dir)

    number_sets = lambda offset: str(offset)
    lowcase_char_sets = lambda offset: chr(97 + offset)
    upcase_char_sets = lambda offset: chr(65 + offset)

    avaliable_sets = []
    for i in range(0, 10):
        avaliable_sets.append(number_sets(i))
    # for i in range(0, 26):
    #     avaliable_sets.append(lowcase_char_sets(i))
    # for i in range(0, 26):
    #     avaliable_sets.append(upcase_char_sets(i))

    def random_str(count):
        str = ""
        for i in range(0, count):
            rand_index = random.randrange(0, len(avaliable_sets) - 1)
            str = str + avaliable_sets[rand_index]
        return str

    image_captcha = image.ImageCaptcha(width=width, height=height)
    for i in range(count):
        captcha_str = random_str(captcha_count)
        image_captcha.write(captcha_str, output_dir + "/" + captcha_str + ".png", "png")
        print("Gen captcha: {0}".format(captcha_str))

def remove_dataset(dir):
    if os.path.exists(dir):
        shutil.rmtree(dir)

def read_dataset(dir):
    images = []
    labels = []
    for subpath in os.listdir(dir):
        if subpath.endswith(".png"):
            image = np.array(PILImage.open(os.path.join(dir, subpath)))
            label = subpath[:-4]
            gray_img = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            images.append(gray_img / 255.0)
            labels.append(label)
    return images, labels


#Criando a tupla
notas = {}

#Perguntando os dados aos usuários
i=1
while i <= 5:
    aluno = input(str("Insira o nome do aluno: "))
    nota = input("Insira a nota de {} no formato X.X: ".format(aluno))
    notas[aluno] = nota
    i= i + 1

#Dicionário com os alunos e as respectivas notas
print(notas)

#Resposta
maiornota = max(notas.values())
def search(term):
    for k, v in notas.items():
        if term in v:
            return k
alunomaiornota = search(maiornota)
print("A maior nota foi a de {}, que tirou {} pontos." .format(alunomaiornota,maiornota))


from typing import List
import unittest

class Solution:
    def carFleet(self, target: int, position: List[int], speed: List[int]) -> int:

        records = [
            (pos, spd) for pos, spd in zip(position, speed)
        ]

        records.sort(key=lambda x: x[0])

        for i in range(len(records)):
            records[i] = (target - records[i][0])/records[i][1]

        stack = []
        for record in records:
            while stack and record >= stack[-1]:
                stack.pop()

            stack.append(record)

        return len(stack)

class TestCases(unittest.TestCase):

    def setUp(self):
        self.sol = Solution().carFleet

    def test_solution_1(self):
        target = 12
        position = [10,8,0,5,3]
        speed = [2,4,1,1,3]
        ans = self.sol(target, position, speed)
        expected = 3
        self.assertEqual(ans, expected)

        target = 100
        position = [0,2,4]
        speed = [4,2,1]
        ans = self.sol(target, position, speed)
        expected = 1
        self.assertEqual(ans, expected)

        target = 10
        position = [3]
        speed = [3]
        ans = self.sol(target, position, speed)
        expected = 1
        self.assertEqual(ans, expected)

if __name__ == '__main__':
    unittest.main()


#UPDATED PAINT/ORGANISED
#calvin and hobbes by Andy Liu

"""
FEATURES

buttons:
-red highlight on hover
-green highlight on click

tools:
-Pencil, only black and thin
-Line, drag and drop
-Oval, drag and drop, left click for filled,right click for unfilled
-Rectangle, see above
-Brush, variable color and size, smoothly connected
-Polygon, left click to add verticies, right click to close poly
-Spray can
-Dropper, click for the color
-Flood fill, fill an enclosed area with a color
-Hilighter, same as brush but translucent
-Eraser, erases to the choosed background
-Clear, Erase everything except choosed background

stamps:
-calvin
-moe
-hobbes
-wagon
-walking
-zombie

functions:
-undo
-redo
-(as png or jpg)
-load (png or jpg, loaded pic becomes choosed background)

music:
-play/pause music
-stop music (if you play again it restarts)

background:
-white
-rocks
-dinosaur
-tree

color choosing:
-wheel picker
-color display

text box:
-position relative to canvas
-color chosen
-button descriptors on hover
"""

"""
STATIC THINGS
only need to do once
"""

#SETUP
#=====================================================

#importing
from random import *
from math import *
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfilename
from pygame import *

#tkinter stuff
root = Tk()
root.withdraw()

#screen
screen = display.set_mode((1280,800))

#background
background = image.load("images/calvin-background.jpg")
screen.blit(background,(0,0))

#canvas
canvas = Rect(50,50,720,540)
draw.rect(screen,(255,255,255),canvas)
draw.rect(screen,(0,0,0),(47,47,726,546),3)        #outside border not inside

#title
titlepng = image.load("images/title.png")
screen.blit(titlepng, (885,14))

#font
font.init()
calibrifont = font.SysFont("Calibri",17)
#======================================================

#MUSIC LOAD AND VOLUME
#========================================================

init()
mixer.music.load("music/slipfunc - amid the flowers..mp3")
mixer.music.play(-1)
mixer.music.set_volume(0.25)

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

#Text Box rectangle
#=========================================================
textbox = (790,430,265,160)
draw.rect(screen,(255,255,255),textbox)
draw.rect(screen,0,textbox,3)

#THE COLOR WHEEL
#========================================================

#wheel
wheel = image.load("images/colorwheel.png")
wheel = transform.smoothscale(wheel,(170,170))
wheelrect = (885,240,170,170)
screen.blit(wheel,(885,240))
draw.rect(screen,(255,255,255),wheelrect,3)

#color display
coldisplay = (1075,288,75,75)
colchoosed = ((1075,288),(1075,363),(1150,288))     #a triangle on the top left corner
draw.rect(screen,(255,255,255),coldisplay)          #later will draw colchoosed with color picked

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

#DRAWING BUTTONS AND PUTTING THEM IN LISTS
#most buttons are 75x75 with 20 px  between
#========================================================

#tool buttons pattern for button places
toolbuts = []
p = 50
for i in range(6):
    draw.rect(screen,(255,255,255),(p,610,75,75))
    draw.rect(screen,(255,255,255),(p,705,75,75))
    toolbuts.append((p,610,75,75))
    toolbuts.append((p,705,75,75))
    p+=95

#stamp buttons
stampbuts = []
q = 695                                            #similar code going down
for j in range(3):
    draw.rect(screen,(255,255,255),(q,610,75,75))
    draw.rect(screen,(255,255,255),(q,705,75,75))
    stampbuts.append((q,610,75,75))
    stampbuts.append((q,705,75,75))
    q+=95

#function buttons
funtsbuts = []
r = 50
for c in range(4):
    draw.rect(screen,(255,255,255),(790,r,75,75))
    funtsbuts.append((790,r,75,75))
    r += 95                                       #pattern goes down instead of across

#music buttons
#special places and sizes (50x50)
musicbuts = []
playbut = (984,631,50,50)
stopbut = (984,726,50,50)
musicbuts.extend((playbut,stopbut))
for place in musicbuts:
    draw.rect(screen,(255,255,255),place)

#background changing buttons

backgroundbuts = []
whitebut = (1075,430,75,75)
draw.rect(screen,(255,255,255),whitebut)
hopsbut = (1170,430,75,75)
dinobut = (1075,515,75,75)
treebut = (1170,515,75,75)
backgroundbuts.extend((whitebut,hopsbut,dinobut,treebut))
#==========================================================

#IMAGE LOADING AND PUT INTO LISTS
#==========================================================

#tool images (logos)
toolimages = []
pencilpng = image.load("images/pencil-icon.png")
linepng = image.load("images/line-icon.png")
ovalpng = image.load("images/oval-icon.png")
rectanglepng = image.load("images/rectangle-icon.png")
brushpng = image.load("images/brush-icon.png")
polypng = image.load("images/poly-icon.png")
spraypng = image.load("images/spraycan-icon.png")
droppng = image.load("images/dropper-icon.png")
fillpng = image.load("images/fill-icon.png")
hilitepng = image.load("images/hilite-icon.png")
erasepng = image.load("images/eraser-icon.png")
erallpng = image.load("images/erall-icon.png")
toolimages.extend((pencilpng,linepng,ovalpng,rectanglepng,brushpng,polypng,spraypng,droppng,fillpng,hilitepng,erasepng,erallpng))

#stamp images
stampimages = []
calvinpng = image.load("images/calvin-stamp.png")
moepng = image.load("images/moe-stamp.png")
hobbespng = image.load("images/hobbes-stamp.png")
wagonpng = image.load("images/wagon-stamp.png")
walkingpng = image.load("images/walking-stamp.png")
zombiespng = image.load("images/zombies-stamp.png")

stampimages.extend((calvinpng,moepng,hobbespng,wagonpng,walkingpng,zombiespng))

#display stamp logos
#already cropped into squares
displayimages = []
calvindisp = image.load("images/calvin-display.png")
moedisp = image.load("images/moe-display.png")
hobbesdisp = image.load("images/hobbes-display.png")
wagondisp = image.load("images/wagon-display.png")
walkingdisp = image.load("images/walking-display.png")
zombiesdisp = image.load("images/zombies-display.png")
displayimages.extend((calvindisp,moedisp,hobbesdisp,wagondisp,walkingdisp,zombiesdisp))

#function images
funtimages = []
undopng = image.load("images/undo-icon.png")
redopng = image.load("images/redo-icon.png")
savepng = image.load("images/save-icon.png")
loadpng = image.load("images/import-icon.png")
funtimages.extend((undopng,redopng,savepng,loadpng))

#music images
musicimages = []
playpng = image.load("images/play-icon.png")
stoppng = image.load("images/stop-icon.png")
musicimages.extend((playpng,stoppng))

#background imagees
#these images are already resized to 720x540 externally
backimages = []
hopspng = image.load("images/hops-canvas.png")
dinopng = image.load("images/dino-canvas.png")
treepng = image.load("images/tree-canvas.png")
backimages.extend(("filler",hopspng,dinopng,treepng))               #filler in the white background spot, makes indexes consistent
#MAKE SURE TO CHACK FOR FILLER LATER

#background display images
#cropped to squares already
backdispimages = []
hopsdisp = image.load("images/hops-display.png")
dinodisp = image.load("images/dino-display.png")
treedisp = image.load("images/tree-display.png")
backdispimages.extend((hopsdisp,dinodisp,treedisp))

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

#RESIZE ALL IMAGES
#faster with lists
#===========================================================

#resize background display images to 75x75
for img in backdispimages:
    backdispimages[backdispimages.index(img)] = transform.smoothscale(img,(75,75))
backdispimages.insert(0,"filler spot")              #fill the zero spot with a filler, make indexes consistent between all background related list AFTER resizing images

#resize tool images to 75x75
for img in toolimages:
    toolimages[toolimages.index(img)] = transform.smoothscale(img,(75,75))

#resize display images to 75x75
for img in displayimages:
    displayimages[displayimages.index(img)] = transform.smoothscale(img,(75,75))

#resize function images to 75x75
for img in funtimages:
    funtimages[funtimages.index(img)] = transform.smoothscale(img,(75,75))

#resize music images to 50x50
for img in musicimages:
    musicimages[musicimages.index(img)] = transform.smoothscale(img,(50,50))

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

#BLIT IMAGES INTO CORRECT SPOTS
#=========================================================

#blit tool images
p = 50
for i in range(6):                                  #same code as defining rectangles but now blitting images in their places instead
    screen.blit(toolimages[2*i],(p,610))            #2 rows of buttons :. this pattern fills every box
    screen.blit(toolimages[2*i+1],(p,705))
    p+=95

#blit display images
q = 695
for i in range(3):                                   #same code again
    screen.blit(displayimages[2*i],(q,610))
    screen.blit(displayimages[2*i+1],(q,705))
    q+=95

#blit function images
r = 50
for i in range(4):
    screen.blit(funtimages[i],(790,r))
    r += 95

#blit music images
screen.blit(musicimages[0],(984,631))
screen.blit(musicimages[1],(984,726))

#blit background display
for i in [1,2,3]:                                   #not index of zero cuz thats the filler button
    (x,y,useless1,useless2) = backgroundbuts[i]
    screen.blit(backdispimages[i],(x,y))
#===========================================================

#COLLECTION OF LISTS
#list of buttons, bools, text and names are all related by order
#in the true/false list whatever place is true is whatever thing is chosen
#using lists for all of this so the code for choosing tools can span loops and not alot of if/else
#===========================================================

#oneselect (tools + stamps) only one can be selected at once
oneselectbuts = toolbuts + stampbuts
oneselectbools = [True] + [False] * 17                              #default pencil
oneselect = ["pencil","line","oval","rectangle","brush","poly","spray","drop",
"fill","hilite","erase","erall","calvin","moe","hobbes","wagon","walking","zombies"]

#functions
funts = ["undo","redo","save","load"]
funtsbools = [False]*4

#music
music = ["play","stop"]
musicbools = [True] + [False]                       #playing music is default

#background
backgroundbools = [True] + [False]*3

#everything
everybuts = oneselectbuts + funtsbuts + musicbuts + backgroundbuts

#text for dialog boxes
#lists inside lists let me blit each item in the inner list on different "lines" using a loop
#last one is blank for when nothing needs to be printed
tooltext = [
    ["Pencil","Draw a thin, black line"],
    ["Line","Draw a straight line"],
    ["Oval","Left click for filled","Right click for unfilled"],
    ["Rectangle","Left click for filled","Right click for unfilled"],
    ["Brush","Draw with a brush effect"],
    ["Polygon","Left click to connect points","Right click to close polygon"],
    ["Spray Can","Draw with a spray can effect"],
    ["Dropper","Click to select the color"],
    ["Fill","Fill the entire canvas"],
    ["Hilighter","Draw a translucent color"],
    ["Eraser","Erase where you click"],
    ["Clear","Erase everything"],
    ["Calvin Stamp"],
    ["Moe Stamp"],
    ["Hobbes Stamp"],
    ["Calvin and Hobbes on wagon Stamp"],
    ["Calvin and Hobbes walking Stamp"],
    ["Zombie Calvin and Hobbes Stamp"],
    ["Undo","Undo your last action"],
    ["Redo","Redo your last action"],
    ["Save","Save the canvas as a PNG or JPG"],
    ["Load","Load a canvas (720x540)"],
    ["Play","Click to pause/play music"],
    ["Stop","Stop the music"],
    ["White Background"],
    ["Hopping on rocks Background"],
    ["Dinosaur Background"],
    ["Sleeping in a tree Background"],
    [" "]
    ]
#===========================================================

"""
ACTIVE PARTS
"""

#DEFAULT OPTIONS
#=========================================================

#undo/redo lists
undolist = []
redolist = []
canvascop = screen.subsurface(canvas).copy()
whitebox = canvascop                                      #for background
undolist.append(canvascop)

#color (black)
r,g,b,a = 0,0,0,0                                   #makes it easier to alter A value
color = r,g,b,a                                     #makes it easier to type

#poly points
points = []

#fill definitions
fillps = set()
fillcol = False                                     #no color

size = 4

#undo/redo perameters
uponcanvas = False
clickoncanvas = False

choosedbackground = whitebox                     #the preselscted background, this defines the variable only at the start
#=======================================================

#START THE WHILE LOOP
#=======================================================

running = True
while running:

    #flags for different events
    click = False
    unclick = False
    left = False
    right = False
    upscroll = False
    downscroll = False

    for e in event.get():

        #event triggers
        if e.type == MOUSEBUTTONDOWN:
            click = True
            if e.button == 1:
                left = True
            if e.button == 3:
                right = True
            if e.button == 4:
                upscroll = True
            if e.button == 5:
                downscroll = True

        if e.type == MOUSEBUTTONUP:
            if e.button == 1 or e.button == 3:      #no mouse wheel plz
                unclick = True

        if e.type == QUIT:
            running = False

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

#TYPICAL MOUSE FUNCTIONS
#========================================================

    mx,my = mouse.get_pos()

    mb = mouse.get_pressed()

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

#SIZE
#=======================================================

#size selecting:
    if upscroll and size<18: #sets max size
        size += 1
    if downscroll and size>4:#sets min size
        size -= 1

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

#CHOOSE COLOR
#========================================================

#color picking:
    if Rect(wheelrect).collidepoint((mx,my)) and (left or right):
        r,g,b,a = screen.get_at((mx,my))                #using both rgba and color so setting A value is easier
        color = r,g,b,a

#display color
    draw.polygon(screen,color,colchoosed)
    draw.rect(screen,color,coldisplay,3)

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

#BUTTON HOVERING
#======================================================

#red if hovering else black. also keep track of the button hovering index for text box later
    hovering = -1
    for place in everybuts:
        if Rect(place).collidepoint(mx,my):
            draw.rect(screen,(255,0,0),place,3)
            ind = everybuts.index(place)
            hovering = ind
        else:
            draw.rect(screen,(0,0,0),place,3)

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

#CLICKING BUTTONS
#THE ONLY WAY FOR A BUTTON TO TURN TRUE IS WITH A CLICK!
#====================================================

#oneselect
    for but in oneselectbuts:
        if Rect(but).collidepoint(mx,my) and (left or right):
            ind = oneselectbuts.index(but)
            oneselectbools = [False]*18
            oneselectbools[ind] = True

#function
    for but in funtsbuts:
        if Rect(but).collidepoint(mx,my) and (left or right):
            ind = funtsbuts.index(but)
            funtsbools = [False]*4
            funtsbools[ind] = True

#combining blitting the background on canvas and turning the button true
#the true is only for green highlight reasons now

#background
    for but in backgroundbuts:
        if Rect(but).collidepoint(mx,my):
            if left or right:
                ind = backgroundbuts.index(but)
                if ind == 0:
                    draw.rect(screen,(255,255,255),canvas)
                    choosedbackground = whitebox                #what the background is at the present moment. used later for erasing and erall purposes
                else:
                    screen.blit(backimages[ind],(50,50))
                    choosedbackground = backimages[ind]         #what the background is rn for future reference
                undolist = []
                undolist.append(choosedbackground)              #reset undolist because selecting a different background is like clearing the screen
                redolist = []
                backgroundbools = [False]*4
                backgroundbools[ind] = True

#music true and false work differently (both can be false at the same time)
#if play is true and you click than play is false
#no need for loop because its only 2 bools long
    #cases for play
    if Rect(musicbuts[0]).collidepoint(mx,my) and (left or right):     #musicbools[0] is the play button
        if musicbools[0]:                                               # if play is true and you click on it, it turns false but stopbut doesn't turn true
            musicbools[0] = False                                   #:. pause NOT stop
        else:
            musicbools[0] = True
            musicbools[1] = False

    #case for stop
    if Rect(musicbuts[1]).collidepoint(mx,my):
        if right or left:
            musicbools = [False]*2
            musicbools[1] = True                    #always turns play to false when you click on stop

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

#WHAT DID YOU CLICK?
#=============================================================================
#every "true" button gets a green border
#drawing green comes after drawing red so its always green
    everybools = oneselectbools + funtsbools + musicbools  + backgroundbools     #every true and false at its current state
    for but in everybuts:
        if everybools[everybuts.index(but)]:
            draw.rect(screen,(0,255,0),but,3)

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

#Text in the text box
#=======================================================

#Reset text box
    draw.rect(screen,(255,255,255),textbox)
    draw.rect(screen,0,textbox,3)

#mouse location on canvas
    mouselocation = calibrifont.render("Mouse position at "+str((mx-50,my-50)),True,(0,0,0))        #canvas starts at 50,50 so subtr 50 to get canvas position
    notoncanvas = calibrifont.render("Not on canvas",True,(0,0,0))
    if Rect(canvas).collidepoint(mx,my):                                                            #in case not on canvas
        screen.blit(mouselocation,(800,447))
    else:
        screen.blit(notoncanvas,(800,447))

#color selected
    colormessage = calibrifont.render("Color = "+str((r,g,b)),True,(0,0,0))                         # A val is useless
    screen.blit(colormessage,(800,470))

#size selected
    sizemessage = calibrifont.render("Size = "+str(size),True,((0,0,0)))
    screen.blit(sizemessage,(800,493))

#tool selected
    d = 516
    for text in tooltext[hovering]:                                                                 #lists inside lists, puts every text short on a new "line"
        toolmessage = calibrifont.render(text,True,(0,0,0))                                         #if hovering == -1 it blits the last text which is nothing
        screen.blit(toolmessage, (800,d))
        d += 23                                                                                #17 ft and 23 space gives 5 pixels of in between

#ACTUALLY DOING MUSIC NOW
#========================================================

#play and pause with music (false = pause) (true = play)
#playbut is play and pause in one place
    if not musicbools[0]:
        mixer.music.pause()
    else:
        if not mixer.music.get_busy():
            mixer.music.play(-1)
        else:
            mixer.music.unpause()

#stop and unstop with music
    if musicbools[1]:
        mixer.music.stop()

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

#SAVE AND LOAD
#=================================================

#save funtbools[2] is the save button
    if funtsbools[2]:
        location = asksaveasfilename()
        if location != "":          #prevents saving to nothing
            image.save(screen.subsurface(canvas),location)
        funtsbools[2] = False       #do not repeat save

#load (funtcools[3] is the load button
    if funtsbools[3]:
        location = askopenfilename(filetypes = [("Picture files", "*.png;*.jpg")])
        if location != "":          #prevents loading from nothing
            screen.set_clip(canvas)
            loaded = image.load(location)
            loaded = transform.smoothscale(loaded,(720,540))
            choosedbackground = loaded
            screen.blit(loaded,(50,50))
        funtsbools[3] = False       #do not repeat load

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

#UNDO AND REDO IS HARD (not anymroe)
#=======================================================

    #UNDO

    #is it drawing?
    if (mb[0] == 1 or mb[2] == 1) and Rect(canvas).collidepoint(mx,my):
        clickoncanvas = True

    #add to undolist after mousebuttonup
    if clickoncanvas:
        if unclick:
            uponcanvas = True
            clickoncanvas = False
            if len(undolist) == 1: #first unclick of the undolist resets the redolist so u cant redo past a blank screen
                redolist = []
        else:
            uponcanvas = False
    else:
        uponcanvas = False

    #adding things to the undolist
    if uponcanvas:
        onthecanvas = screen.subsurface(canvas).copy()
        undolist.append(onthecanvas)

    #the actual undoing
    #blit the second last and move the last into redolist, check for length so no crashes
    if funtsbools[0]:
        if len(undolist)>1:
            screen.blit(undolist[-2],(50,50))
            redolist.append(undolist[-1])
            del undolist[-1]
        funtsbools[0] = False

    #REDO
    #blit the last and move it to undolist again
    if funtsbools[1]:
        if len(redolist)>0:
            screen.blit(redolist[-1],(50,50))
            undolist.append(redolist[-1])
            del redolist[-1]
        funtsbools[1] = False

#DRAWING STUFF!
#everything after this point has to do with drawing
#======================================================

    screen.set_clip(canvas)

    for trueorfalse in oneselectbools:
        if trueorfalse:     #if true :. it was clicked
            if mb[0] == 1:  #filled things and normal tools here

                #pencil
                if oneselect[oneselectbools.index(trueorfalse)] == "pencil":        #only one bool in list is true :. index(trueorfalse) always has the right target, this is a way to jump from related lists
                    draw.line(screen,(0,0,0),(omx,omy),(mx,my),2)                     #always black, always size of 2., drawing a line from omx,omy to mx,my makes sure theres never any holes in the line

                #line
                if oneselect[oneselectbools.index(trueorfalse)] == "line":
                    if left:                                                        #set starting point
                        startingx,startingy = mx,my
                        cop = screen.copy()
                    hyp = int(hypot(mx-startingx,my-startingy))
                    screen.blit(cop,(0,0))                                          #so the line can "move" wothout drawing on the canvas until you unclick
                    for i in range(hyp):                                            #draws a circle at every 1 interval of the hypotenuse
                        draw.circle(screen,color,(startingx+int((mx-startingx)/hyp*i),startingy+int((my-startingy)/hyp*i)),size) #similar triangles math all in one line

                #filled oval
                if oneselect[oneselectbools.index(trueorfalse)] == "oval":          #see above
                    if left:
                        startingx,startingy =mx,my
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    circrect = Rect(startingx,startingy,mx-startingx,my-startingy)
                    circrect.normalize()
                    draw.ellipse(screen,color,circrect)

                #filled rectangle
                if oneselect[oneselectbools.index(trueorfalse)] == "rectangle":     #see above
                    if left:
                        startingx,startingy =mx,my
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    draw.rect(screen,color,(startingx,startingy,mx-startingx,my-startingy))

                #brush
                if oneselect[oneselectbools.index(trueorfalse)] == "brush":
                    hyp = int(hypot(mx-omx,my-omy))
                    for i in range(hyp):
                        draw.circle(screen,color,(omx+int((mx-omx)/hyp*i),omy+int((my-omy)/hyp*i)),size) #see above (similar triangles)

                #polygon is special, so it's skipped for now

                #spraycan, 20 at a time is a good speed, pick random points
                if oneselect[oneselectbools.index(trueorfalse)] == "spray":
                    for i in range(20):
                        rand1 = randint(size*-1,size)
                        rand2 = randint(size*-1,size)
                        if hypot(rand1,rand2) <= size:
                            screen.set_at((mx+rand1,my+rand2),color)

                #dropper, selects the color you click
                if oneselect[oneselectbools.index(trueorfalse)] == "drop":
                    if Rect(canvas).collidepoint(mx,my):
                        r,g,b,a = screen.get_at((mx,my))                            #have to change both rgba and color to be consistent
                        color = r,g,b,a

                #hiliter (translucent brush)
                if oneselect[oneselectbools.index(trueorfalse)] == "hilite":
                    #what the hilite looks like
                    circscreen = Surface((size*2,size*2),SRCALPHA)
                    draw.circle(circscreen,(r,g,b,5),(size,size),size)
                    #put it on
                    hyp = int(hypot(mx-omx,my-omy))
                    for i in range(hyp):
                        screen.blit(circscreen,((omx+int((mx-omx)/hyp*i))-size,(omy+int((my-omy)/hyp*i))-size)) #the -size centers the surface(circle) to mouse

                #eraser
                if oneselect[oneselectbools.index(trueorfalse)] == "erase":

                #the variable erasing is what you need to blit on screen, different cases for erasing depending on background

                    #define erasing when it is a white background
                    if choosedbackground == whitebox:                #white square with dimensions 2sizex2size
                        erasing = Surface((size*2,size*2))
                        erasing.fill(16777215)
                    else:
                        picturesurface = Surface((1280,800))            #makes the subsurface thats the choosed background (same relativer mx and my)
                        picturesurface.blit(choosedbackground,(50,50))

                    hyp = int(hypot(mx-omx,my-omy))
                    for i in range(hyp):

                        #define erasing when not whitebackground
                        if choosedbackground != whitebox:

                            try:#try and except statements because this code sometimes crashes when you move the mouse too fast but if you skip the crashing case everything around it "fills its place" and it looks fine either way
                                erasing = picturesurface.subsurface(int(omx+int((mx-omx)/hyp*i))-size,int(omy+int((my-omy)/hyp*i))-size,size*2,size*2)      #added int() so everything works
                            except:
                                pass

                        try:
                            screen.blit(erasing,((omx+int((mx-omx)/hyp*i))-size,(omy+int((my-omy)/hyp*i))-size))
                        except:
                            pass

                #clear canvas, points list (poly), undolist (except for first) and redolist)
                if oneselect[oneselectbools.index(trueorfalse)] == "erall":
                    if choosedbackground == whitebox:
                        draw.rect(screen,16777215,canvas)
                    else:
                        screen.blit(choosedbackground,(50,50))
                    points = []
                    undolist = [undolist[0]]
                    redolist = []

            if mb[2] == 1:#unfilled shapes by rightclicking

                #unfilled ellipse
                #checked for ellipse radius greater than width
                if oneselect[oneselectbools.index(trueorfalse)] == "oval":                  #same code as filled
                    if right:
                        startingx,startingy =mx,my
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    circrect = Rect(startingx,startingy,mx-startingx,my-startingy)
                    circrect.normalize()
                    if circrect.h > 2*size and circrect.w > 2*size:
                        draw.arc(screen,color,circrect,0,360,size)
                    else:
                        draw.ellipse(screen,color,circrect)

                #unfilled rectangle
                if oneselect[oneselectbools.index(trueorfalse)] == "rectangle":             #same code as filled rect
                    if right:
                        startingx,startingy = mx,my
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    unfilled = Rect(startingx,startingy,mx-startingx,my-startingy)
                    evensize = size+size%2
                    draw.rect(screen,color,unfilled,evensize)
                    draw.rect(screen,color,(startingx-(evensize)//2+1,startingy-(evensize)//2+1,evensize,evensize))     #next 4 lines fill in the corners of the rectangle
                    draw.rect(screen,color,(startingx-(evensize)//2+1,my-(evensize)//2,evensize,evensize))              #the various +1's eliminate pygame inconsistencies
                    draw.rect(screen,color,(mx-(evensize)//2,startingy-(evensize)//2+1,evensize,evensize))              #(found by trial)
                    draw.rect(screen,color,(mx-(evensize)//2,my-(evensize)//2,evensize,evensize))

    for trueorfalse in oneselectbools:
        if trueorfalse:

            #polygon is a special tool using both clicks :. in seperate loop
            if oneselect[oneselectbools.index(trueorfalse)] == "poly":
                if Rect(canvas).collidepoint(mx,my):
                    if left:
                        points.append((mx,my))                                          #put mouse pos in list when you left click
                        cop = screen.copy()

                    #size set on first click
                    if len(points) == 0:
                        setsize = size

                    #drawing "line" from the last clicked position to current mouse position
                    if len(points)>0:
                        lastx,lasty = points[-1]
                        hyp = int(hypot(mx-lastx,my-lasty))
                        screen.blit(cop,(0,0))
                        for i in range(hyp):
                            draw.circle(screen,color,(lastx+int((mx-lastx)/hyp*i),lasty+int((my-lasty)/hyp*i)),setsize)

                    #right click to close polygon between first and last points in pointlist
                    if right:
                        points.append((mx,my))
                        if len(points) > 0:
                            end1x,end1y = points[-1]
                            end2x,end2y = points[0]
                            hyp = int(hypot(end2x-end1x,end2y-end1y))
                            for i in range(hyp):
                                draw.circle(screen,color,(end1x+int((end2x-end1x)/hyp*i),end1y+int((end2y-end1y)/hyp*i)),setsize)

                            #resetting
                            points = []

    for trueorfalse in oneselectbools: #more loop beginnings needed to take care of case where polygon is used and so nothing is true therefore fill
        #cannot exist in loop because nothing is true
        if trueorfalse:

            #fill is a special tool using a points set
            #change every adjacent color with the same color
            #initial click point and color
            if oneselect[oneselectbools.index(trueorfalse)] == "fill": #if tool is fill

                #first click
                if (left or right) and Rect(canvas).collidepoint(mx,my) and screen.get_at((mx,my)) != color:
                    fillps.add((mx,my))
                    fillcol = screen.get_at((mx,my))
                    screen.set_at((mx,my),color)

                #while loop goes through every adjacent pixel from the click and spreads out, applicable pixels only need to be put in the set once
                if fillcol != False:
                    while len(fillps)>0:
                        fx,fy = fillps.pop()
                        for adx in [-1,1]:
                            for ady in [-1,1]:
                                if screen.get_at((fx+adx,fy+ady)) == fillcol and ((fx+adx,fy+ady) not in fillps):
                                    fillps.add((fx+adx,fy+ady))
                                    screen.set_at((fx+adx,fy+ady),color)

                    #reset after loop
                    fillps = set()

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

#STAMPS
#same code for every stamp
#==============================================================

    #a bit of debugging
    #if any function button is clicked while a stamp is selected it will blit it and do the function at the same time and cause problems
    functionclick = False
    for but in funtsbuts:
        if Rect(but).collidepoint(mx,my):
            functionclick = True

    for trueorfalse in oneselectbools:
        if trueorfalse:
            if mb[0] == 1 and not functionclick:

                #calvin stamp
                if oneselect[oneselectbools.index(trueorfalse)] == "calvin":
                    length,width = calvinpng.get_rect().size                    #gets dimensions of image
                    if left:
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    screen.blit(calvinpng,(mx-length//2,my-width//2))           #centers image to mouse

                #moe stamp
                if oneselect[oneselectbools.index(trueorfalse)] == "moe":
                    length,width = moepng.get_rect().size
                    if left:
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    screen.blit(moepng,(mx-length//2,my-width//2))

                #hobbes stamp
                if oneselect[oneselectbools.index(trueorfalse)] == "hobbes":
                    length,width = hobbespng.get_rect().size
                    if left:
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    screen.blit(hobbespng,(mx-length//2,my-width//2))

                #wagon stamp
                if oneselect[oneselectbools.index(trueorfalse)] == "wagon":
                    length,width = wagonpng.get_rect().size
                    if left:
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    screen.blit(wagonpng,(mx-length//2,my-width//2))

                #walking stamp
                if oneselect[oneselectbools.index(trueorfalse)] == "walking":
                    length,width = walkingpng.get_rect().size
                    if left:
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    screen.blit(walkingpng,(mx-length//2,my-width//2))

                #zombies stamp
                if oneselect[oneselectbools.index(trueorfalse)] == "zombies":
                    length,width = zombiespng.get_rect().size
                    if left:
                        cop = screen.copy()
                    screen.blit(cop,(0,0))
                    screen.blit(zombiespng,(mx-length//2,my-width//2))

    screen.set_clip()
    omx,omy = mx,my
#==============================================================
    display.flip()
quit()


# https://leetcode.com/problems/subsets/
# Total subsets for an arr of len n is 2 power n
# Each subset is represented by binary representation of this total
# for ex. if n = 3
# total subsets is 8 viz. 2 power 3
# subset0 would be 000, subset1 = 001, subset2 = 010, subset3 = 011 and so on.
# if one is found in binary number then include num[index] where index is position of 1 in binary number
# for ex in 000 donot include any item in subset
# for 001 include only 3rd item (nums[2]) in subset
# for 010 include 2nd item (nums[1]) in subset
# 011 include 2nd and 3rd item (nums[1] and nums[2]) in subset

from typing import List

class Solution:
    def _getbinary(self, num):
        res: List[int] = []
        while num > 0:
            mod = num % 2
            res.append(mod)
            num = num // 2
        return res

    def subsets(self, nums: List[int]) -> List[List[int]]:
        # init list
        res: List = []
        total= pow(2, len(nums))
        for i in range(total):
            bin_arr = self._getbinary(i)
            index: int = 0
            sub_set: List[int] = []
            while(index < len(bin_arr)):
                if (bin_arr[index] == 1):
                    sub_set.append(nums[index])
                index += 1
            res.append(sub_set)
        return res

if __name__ == '__main__':
    print(Solution().subsets([1, 2, 3]))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/3/27 16:43
# @Author  : TanLHHH
# @Site    :
# @File    : tieba.py
# @Software: PyCharm

import requests,re

url = "https://tieba.baidu.com/f?kw=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92&ie=utf-8&pn=0"

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
    "Host": "tieba.baidu.com"
}

res = requests.get(url=url,headers=headers)
#print(res.content.decode('utf-8'))

pat = '<a rel="noreferrer" href="/p/(.*?)" title="(.*?)" target="_blank" class="j_th_tit ">'
title_list = re.compile(pat, re.S).findall(res.content.decode('utf-8'))

#url_pat = 'class="frs-author-name j_user_card " href="(.*?)" target="_blank">'

pat = 'title="主题作者:.*?".*? href="/home/main/(.*?)" target="'

url_list = re.compile(pat,re.S).findall(res.content.decode('utf-8'))
print(res.content.decode('utf-8'))
# print(res.status_code)
# print(title_list)
# print(title_list[0][0],title_list[0][1])
print(url_list)
print(len(url_list))


import json
import networkx as nx
import matplotlib.pyplot as plt

def get_topology(edges):

    g = nx.Graph()

    l3edges_json = json.loads(edges.to_json(orient="index"))
    for k in l3edges_json:
        neighbor = l3edges_json[k]
        node_id = neighbor["Interface"]["hostname"]
        remote_node_id = neighbor["Remote_Interface"]["hostname"]
        g.add_edge(node_id, remote_node_id)

    return g

def get_figure(pframe):
    """
    Plots Pandas data frame

    """
    g = get_topology(pframe)

    # Calculate spring layout
    pos = nx.spring_layout(g)

    # Draw the graph using matplotlib within Streamlit
    fig, ax = plt.subplots()
    nx.draw(g, pos, with_labels=True, ax=ax, node_size=1000, font_color="white")

    return fig


# -*- coding: utf-8 -*-
"""
Created on Tue Jul 23 14:40:11 2019

@author: hoangt1
"""
#ANSWER: 748317
#NOTE: 1 is not prime

def reversed_num(n):
    reversed_n=0
    while(n>0):
        remainder=n%10
        reversed_n=reversed_n*10+remainder
        n=n//10
    return reversed_n

def is_prime(n):
    if n==1: return 0
    for i in range(2,int(n**0.5)+1):
        if n%i==0: return 0
    return 1

def is_truncatable_prime(n):
    if not is_prime(n): return 0

    # right -> left truncation
    n1=n
    n2=n
    while n1>10:
        r2l_trunc=n1//10
        if not is_prime(r2l_trunc):
            return 0
        n1=r2l_trunc
    # left -> right truncation
    while n2>10:
        rev_n=reversed_num(n2)
        l2r_truc=reversed_num(rev_n//10)
        if not is_prime(l2r_truc):
            return 0
        n2=l2r_truc
    return 1

def calculation():
    n=11
    counter=0
    s=0
    while(counter<11):
        n+=2 #Only odd numbers will be checked
        if is_truncatable_prime(n):
            print(n)
            counter+=1
            s+=n
    print(s)

calculation()


from flask import Flask,render_template,redirect,url_for
from flask_bootstrap import Bootstrap
from detail_collector import DetailCollector

app = Flask(__name__)
app.config['Secret_KEY'] = '83hs293C0926jcw2FJ893Bd3E'

Bootstrap(app)

detail = DetailCollector()

@app.route("/")
@app.route("/home")
def home():
    return render_template('index.html',details = detail)


from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Account, UserProfile, RefundRequests, FavoriteItem, Preferences

# Register your models here.

class AccountAdmin(UserAdmin):
    list_display = ('email', 'first_name', 'last_name', 'username', 'phone_number', 'last_login', 'date_joined', 'is_active')
    list_per_page = 60
    filter_horizontal = ()
    list_filter = ()
    fieldsets = ()
    ordering = ('date_joined',)

class UserProfileAdmin(admin.ModelAdmin):
    list_display = ('user', 'city', 'district', 'province', 'country')
    list_per_page = 30

class PreferencesAdmin(admin.ModelAdmin):
    list_display = ('user', 'product', 'rating')
    list_per_page = 30

class RefundRequestsAdmin(admin.ModelAdmin):
    list_display = ('user', 'order_number', 'amount_paid','processed','created_at')
    list_editable = ('processed',)
    list_per_page = 30

admin.site.register(Account,AccountAdmin)
admin.site.register(UserProfile, UserProfileAdmin)
admin.site.register(RefundRequests, RefundRequestsAdmin)
admin.site.register(FavoriteItem)
admin.site.register(Preferences,PreferencesAdmin)


from queue import PriorityQueue
class Solution:
    def splitNum(self, num: int) -> int:
        a=[int(x) for x in str(num)]
        pq=PriorityQueue()
        num1=""
        num2=""
        for i in a:
            pq.put(i)

        while not pq.empty():
            num1+=str(pq.get())
            if not pq.empty():
                num2+=str(pq.get())

        return int(num1)+int(num2)


import csv
import itertools
import os.path
import sys

if __name__ == "__main__":
    #Create ontology dictionary from MEGARes ontology file
    #megares_ontology = {}
    #ontology_filename = "/home/noyes046/jsettle/argmobrich/MEGARESONTOLOGY.tsv"
    #with open(ontology_filename, 'r') as ontology_tsv:
        #ontology_reader = csv.reader(ontology_tsv, delimiter='\t')
        #for row in ontology_reader:
            ##Skip column names
            #if row[0] == "header":
                #continue
#
            ##FIll in our dict
            #megares_ontology[row[0]] = { "class"        : row[1],
                                         #"mechanism"    : row[2],
                                         #"group"        : row[3]
                                       #}

    #Go through colocalization results, looking for overlaps
    results_filename = sys.argv[1]
    overlap_dict ={}
    tmp_overlaps = []
    with open(results_filename, 'r') as results_csv:
        results_reader = csv.reader(results_csv, delimiter='\t')
        for row in results_reader:
            #Skip column names
            if row[0] == "SAMPLE_TYPE":
                continue

            if row[18] == "No":
                #If there were overlaps, record them
                if len(tmp_overlaps) > 1:
                    overlaps_processed = []
                    for overlap in itertools.product(tmp_overlaps, repeat=2):
                        #Not interested in alignments to same read
                        if overlap[0] == overlap[1]:
                            continue

                        #(A,B) = (B,A) for this purpose
                        if (tuple(sorted(overlap)) in overlaps_processed):
                            continue

                        if overlap in overlap_dict:
                            overlap_dict[overlap] += 1
                        else:
                            overlap_dict[overlap] = 1
                        overlaps_processed.append(tuple(sorted(overlap)))

                tmp_overlaps = [row[11]]
            else: #(row[16] == "Yes")
                tmp_overlaps.append(row[11])

    sorted_overlaps = sorted(overlap_dict, key = lambda overlap: overlap_dict[overlap], reverse=True)

    #Write tsv for overlap counts
    with open(os.path.splitext(os.path.basename(sys.argv[1]))[0] + "_overlaps.tsv", 'w') as coloc_tsv:
        coloc_writer = csv.writer(coloc_tsv, delimiter='\t')
        coloc_writer.writerow([os.path.splitext(os.path.basename(sys.argv[1]))[0][:6] + " overlaps"])
        coloc_writer.writerow([])
        coloc_writer.writerow(["Overlap Pair", "Occurrences"])
        for overlap in sorted_overlaps:
            coloc_writer.writerow([overlap, overlap_dict[overlap]])