import random
import math

from elvenfire import bonus5
from elvenfire.labyrinth import s

class Trap:

    """Abstract class used to define common code for all potential Traps."""

    def __init__(self):
        """Initialize all common values to None."""
        self.name = None
        self.explanation = None
        self.detect = self.remove = self.avoid = None
        self.numdice = self.diesize = None
        self.extrainfo = None

    def newtrap(level):
        """Class method: generate and return a new Trap of random type."""
        type = random.randint(1, 100)
        if type <= 11:
            return ExplosiveTrap(level)
        elif type <= 30:
            return MissileTrap(level)
        elif type <= 45:
            return GasTrap(level)
        elif type <= 55:
            return LiquidTrap(level)
        elif type <= 65:
            return EtherealTrap(level)
        elif type <= 80:
            return PitTrap(level)
        elif type <= 97:
            return OtherTrap(level)
        else:
            return SpecialTrap(level)

    def __str__(self):
        """Return a description suitable for explanation to the players."""
        val = "  Potential %s trap" % self.name
        if self.explanation is not None:
            val += " (%s)" % self.explanation
        val += "\n    Requires %svIQ to detect, " % self.detect
        val += "%svDx to remove, and %svDx to avoid." % (self.remove, self.avoid)
        if self.numdice is not None:
            val += "\n    Inflicts %sd%s hits if triggered." % \
                   (self.numdice, self.diesize)
        if self.extrainfo is not None:
            val += "\n    " + self.extrainfo
        return val

class ExplosiveTrap (Trap):

    """Potential trap featuring some type of explosive."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1,3)
        self.detect = int(level * 2 + (4 - math.sqrt(random.uniform(0, 9))))
        self.remove = int(size + level * 3 + (6 - math.sqrt(random.uniform(0, 9))))
        self.avoid = int(size + level + (4 - math.sqrt(random.uniform(0, 9))))
        self.numdice = int(size + level - 1)
        self.diesize = 6
        if size == 3:
            self.name = 'large explosive'
            self.explanation = '2/3 dmg in adjacent hex, 1/3 two hexes away'
        elif size == 2:
            self.name = 'medium explosive'
            self.explanation = '1/2 damage in adjacent hex'
        else:
            self.name = 'small explosive'
            self.explanation = None

class MissileTrap (Trap):

    """Potential trap featuring some form of physical missile weapon."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1,8)
        self.detect = int(level * 2 + (5 - math.sqrt(random.uniform(0, 16))))
        self.remove = int(size + level * 3 + (5 - math.sqrt(random.uniform(0, 16))))
        self.avoid = int(size + level + (3 - math.sqrt(random.uniform(1, 4))))
        if (size < 3):
            self.numdice = level
            self.diesize = 6
            self.name = 'piercing arrow'
            self.explanation = s(self.numdice, 'arrow')
        elif (size < 4):
            self.numdice = level
            self.diesize = 8
            self.name = 'broadhead arrow'
            self.explanation = s(self.numdice, 'arrow')
        elif (size < 6):
            self.numdice = level
            self.diesize = 10
            self.name = 'crossbow bolt'
            self.explanation = s(self.numdice, 'bolt')
        elif (size < 7):
            self.numdice = level
            self.diesize = 20
            self.name = 'explosive crossbow bolt'
            self.explanation = s(self.numdice, 'bolt')
        elif (size < 8):
            self.numdice = level
            self.diesize = 12
            self.name = 'spear'
            self.explanation = s(self.numdice, 'spear')
        else:
            self.numdice = 1 + int(level/2)
            self.diesize = 12
            self.name = 'scything blade'
            self.explanation = '1 blade'
        self.extrainfo = "Randomly identify SOURCE of each missile " + \
                         "triggered; then 'roll to miss'"

class GasTrap (Trap):

    """Potential trap featuring some type of poison gas."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1, 10)
        self.detect = int(1 + level + 4 - math.sqrt(random.uniform(0, 9)))
        self.remove = int(level * 2 + (4 - math.sqrt(random.uniform(0, 9))))
        self.avoid = int(level + (4 - math.sqrt(random.uniform(0, 9))))
        saving = 3 + level
        self.explanation = "%svSt if triggered to avoid effects" % saving
        self.numdice = self.diesize = None
        if size < 3:
            self.name = 'poison gas'
            self.extrainfo = "Poison causes d8 damage, ignore armor / shields" + \
                             " or other hit protection"
        elif size < 4:
            self.name = 'sleeping gas'
            self.extrainfo = "Sleep for 2d6 minutes; if 12, then d4 days" + \
                             "\n      " + \
                             " (roll for wandering creatures each minute)"
            #duration = random.randint(2, 12)
            #self.extrainfo = "Sleep for %s minutes" % duration + \
            #                 " (roll for wandering creatures each minute)"
            #if duration == 12:
            #    duration = random.randint(1, 4)
            #    self.extrainfo = "Sleep for %s days" % duration
        elif size < 5:
            self.name = 'blinding gas'
            self.extrainfo = "Blind (Dx-8) for 2d6 minutes (roll for" + \
                             " wandering creatures each minute);\n      " + \
                             " if 12, then d12 hours."
        elif size < 6:
            self.name = 'slow gas'
            if (random.randint(1, 6) == 6):
                effect = "1/3 MA (round down)"
            else:
                effect = "1/2 MA (round down)"
            self.extrainfo = "If triggered, %s for d4 battles" % effect
        elif size < 7:
            self.name = 'chlorine gas'
            self.extrainfo = "Chlorine causes d12 damage, ignore armor," + \
                             " shields, and other hit protection"
        elif size < 8:
            self.name = 'corroding gas'
            self.explanation = "artifacts get 3vDx roll to avoid damage"
            self.extrainfo = "Destroys metallic armor and shields."
        else:
            self.name = 'attribute-affecting gas'
            self.explanation = "%svAttr if triggered to avoid effects" % saving
            attr = random.choice(('strength', 'dexterity', 'intelligence'))
            dmg = random.randint(1, 2*level)
            self.extrainfo = "Reduces %s by %s for d4 battles." % (attr, dmg)

class LiquidTrap (Trap):

    """Potential trap featuring some type of damaging liquid."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1, 10)
        self.detect = int(level * 2 + (4 - math.sqrt(random.uniform(0, 9))))
        self.remove = int(size + level * 3 + (6 - math.sqrt(random.uniform(0, 25))))
        self.avoid = int(size + level + (4 - math.sqrt(random.uniform(0, 9))))
        self.explanation = "armor doesn't protect"
        if size < 6:
            self.name = 'flaming oil'
            self.extrainfo = "Will burn for d8 rounds, inflicting 2" + \
                             " additional hits per round."
            self.numdice = level
            self.diesize = 6
        elif size < 8:
            self.name = 'acid'
            self.numdice = 1 + level
            self.diesize = 8
        else:
            self.name = 'contact poison'
            self.avoid *= 2
            self.remove = int(self.remove / 2 + 1)
            self.numdice = level
            self.diesize = 6

class EtherealTrap (Trap):

    """Potential trap featuring some type of mental ability."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1, 10)
        self.detect = int(level * 2 + (4 - math.sqrt(random.uniform(0, 9))))
        self.remove = int(size + level * 3 + (6 - math.sqrt(random.uniform(0, 25))))
        self.avoid = int(size + level + (4 - math.sqrt(random.uniform(0, 9))))
        if size < 6:
            type = random.choice(('Lightning Bolt', 'Ether Arrow', 'Iceball',
                                  'Fireball', 'Boulder'))
            self.name = "Ethereal Bow (%s)" % type
            self.numdice = bonus5(level)
            self.diesize = 2 * (level + random.randint(1, 2*level))
            self.diesize = min((12, self.diesize))
            self.detect *= 2
            self.avoid *= 2
        elif size < 8:
            self.name = 'shock'
            self.explanation = 'does double damage if wearing metal armor'
            self.numdice = bonus5(level)
            self.diesize = 2 * random.randint(1, 4*level)
            self.diesize = min((10, self.diesize))
            self.avoid -= 1
            self.remove += 1
        else:
            self.name = 'teleporter'
            self.explanation = 'd6 direction for d10 megahexes'
            self.numdice = 1
            self.diesize = 4
            self.remove *= 3

class PitTrap (Trap):

    """Potential trap featuring some type of trapdoor or pit."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1, 10)
        self.detect = int(level * 2 + (5 - math.sqrt(random.uniform(0, 16))))
        self.remove = int(level * 3 + (6 - math.sqrt(random.uniform(0, 25))))
        self.avoid = int(level * 2 + (3 - math.sqrt(random.uniform(0, 4))))
        depth = 5 * random.randint(1, 2 * level)
        if size < 3:
            self.name = '%s-meter deep empty pit' % depth
            self.numdice = round(depth / 5)
            self.diesize = 4
        elif size < 4:
            self.name = '%s-meter deep spiked pit' % depth
            self.numdice = round(depth / 5)
            self.diesize = 6
        elif size < 5:
            self.name = '%s-meter deep viper pit' % depth
            self.explanation = 'd4/round until escape'
            self.numdice = round(depth / 5)
            self.diesize = 4
        elif size < 6:
            self.name = '%s-meter deep water-filled pit' % depth
            self.explanation = 'swim or drown'
            self.numdice = 1
            self.diesize = 4
        elif size < 7:
            self.name = '%s-meter deep flooding pit' % depth
            self.explanation = 'swim or drown'
            self.numdice = round(depth / 5)
            self.diesize = 4
        else:
            self.name = 'trapdoor to next level'
            self.numdice = round(depth / 5)
            self.diesize = 4

class OtherTrap (Trap):

    """Miscellaneous potential trap types."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        size = random.randint(1, 15)
        self.detect = int(level * 2 + (4 - math.sqrt(random.uniform(0, 9))))
        self.remove = int(level * 3 + (6 - math.sqrt(random.uniform(0, 25))))
        self.avoid = int(level + (4 - math.sqrt(random.uniform(0, 9))))
        if size < 8:
            self.name = 'scorpion'
            self.explanation = '50% chance of sting/round trying to pick lock'
            self.numdice = 1
            self.diesize = 8
            self.detect -= 1
            self.remove = 3
        elif size < 11:
            self.name = 'ball pendulum'
            self.numdice = bonus5(level)
            self.diesize = 4 + 2 * level
            self.remove -= 1
        elif size < 13:
            self.name = 'blade pendulum'
            self.numdice = bonus5(level)
            self.diesize = 8 + 2 * level
            self.remove -= 1
        elif size < 14:
            area = 3 + random.randint(0, 9)
            self.name = 'collapsing ceiling'
            self.explanation = 'covers %s hexes' % area
            self.numdice = bonus5(level)
            self.diesize = 2 * random.randint(level, level + 1)
            self.remove -= 2
            self.avoid += 1
        else:
            self.name = 'rolling ball'
            self.explanation = 'select edge hex & direction,' + \
                               ' moves 10/round'
            self.numdice = 1 + random.randint(level, level + 1)
            self.diesize = 8
        self.diesize = min((12, self.diesize))

class SpecialTrap (Trap):

    """Potential trap featuring some type of special effect."""

    def __init__(self, level):
        """Determine required die rolls and damage."""
        Trap.__init__(self)  # set all variables to None
        self.detect = int(level * 4 + (4 - math.sqrt(random.uniform(0, 9))))
        self.remove = int(1 + level + 4 - math.sqrt(random.uniform(0, 9)))
        self.avoid  = int(1 + level + 4 - math.sqrt(random.uniform(0, 9)))
        type = random.randint(1, 10)
        if type <= 4:
            self.name = 'minor disease'
            self.explanation = 'ST-1 until healed'
        elif type <= 7:
            dx = random.randint(11, 17)
            self.name = 'animate weapon'
            self.explanation = 'DX = %s, d4 damage' % dx
            self.remove += random.randint(1, 3)
            self.avoid += random.randint(1, 2)
        elif type <= 9:
            self.name = 'destroy one artifact'
            self.remove += random.randint(1, 3)
            self.avoid += random.randint(1, 2)
        else:
            self.name = 'lose 1 attribute point'
            self.remove += 1
            self.avoid += random.randint(1, 2)


import numpy as np
import pandas as pd
from sklearn import metrics
import datetime

stim_path = 'organized/stim_times/stimTimes_835HLS1left_0.csv'
#file_path = 'organized/835HLS1right_1/dff_835HLS1right_1.csv'

df = pd.read_csv('scaled_835leftHLS1_sensory0.csv')
#df2 = df.copy(deep=True)

print(df.head())
print(df.dtypes)

###Initialize Variables

dFF = 'dFF'
time = 'Time'
zdFF = 'zDFF'

### Get stimulation timepoints and sync them
stimsDF = pd.read_csv(stim_path, names=['file', 'index', 'timestamps', 'limb', 'stim_type'])
time_list = stimsDF['timestamps'].tolist()
stims = []
for t in range(len(time_list)):
    try:
        date_time = datetime.datetime.strptime(time_list[t], "%M:%S.%f")
    except:
        stims.append(float(time_list[t]))
        continue
    a_timedelta = date_time - datetime.datetime(1900, 1, 1)
    seconds = a_timedelta.total_seconds()
    stims.append(seconds)
print("Stims:", stims)

#get synced trial times
cal_start = 8.0644
vid_start = 5.647
trials = []
for count in range(len(stims)):
    trial= stims[count] - vid_start + cal_start
    trials.append(trial)

### Whole Trace calculations
median = round(float(np.median(df['dFF'])),4)
sd     = round(float(np.std(df['dFF'])),4)
mean   = round(float(np.mean(df['dFF'])),4)

prc50 = np.percentile(df['dFF'],50)
#print(prc50)

meanLT50 = np.mean(df['dFF'].loc[df['dFF'] <= prc50])
medLT50 = np.median(df['dFF'].loc[df['dFF'] <= prc50])
sdLT50 = np.std(df['dFF'].loc[df['dFF'] <= prc50])

thresholdMed = median + (2*sd)

### Calculate z-score dFF
df['zDFF'] = (df['dFF'] - meanLT50) / sdLT50
sdZDFF= np.std(df['zDFF'])

prc50Z = np.percentile(df['zDFF'],50)
sdLT50Z = np.std(df['zDFF'].loc[df['zDFF'] <= prc50Z])

### Calculate mean and standard deviation for the (X) seconds before stimulation
baselines = []
sds       = []
for stim in trials:
     begin = stim - 3.0
     end   = stim

     in_between = df['Time'].between(begin, end, inclusive=True)

     baselines.append(np.mean(df['dFF'].loc[in_between]))
     sds.append(np.std(df['dFF'].loc[in_between]))

### Calculate AUC while above threshold

##Find AUC
aucBeforeStim = []
aucAfterStim  = []
aucDuringPeak = []
aucDuringPeakZ = []
aucBeforeStimZ = []
aucDuringPeakMean =[]

durationsMed = []
durationsMean = []
durationsZ = []

# Get thresholds for latency of response

latencyMed = []
latencyMean = []
latencyZ = []

no_cross=0
for i in range(len(trials)-1):
    auc1start = trials[i] - 3
    auc1end   = trials[i]
    auc2start = trials[i]
    auc2end   = trials[i] + 5
    stim1 = trials[i]
    stim2 = trials[i+1]

    in_between1 = df['Time'].between(auc1start, auc1end, inclusive=True)
    in_between2 = df['Time'].between(auc2start, auc2end, inclusive=True)
    peak_indx = df.index[(df['Time'].between(stim1,stim2)) & (df['dFF'] >= medLT50)].tolist()
    peak_indxMean = df.index[(df['Time'].between(stim1,stim2)) & (df['dFF'] >= baselines[i])].tolist()
    peak_indxZ = df.index[(df['Time'].between(stim1,stim2)) & (df['zDFF'] >= 1.65)].tolist()
    try:
        peak_start = peak_indx[0]
        peak_end   = peak_indx[-1]
        peak_startMean= peak_indxMean[0]
        peak_endMean = peak_indxMean[-1]
        peak_startZ = peak_indxZ[0]
        peak_endZ   = peak_indxZ[-1]
    except:
        print(i)
        no_cross+=1
        continue

    ##Get duration while response was above threshold
    duration = df['Time'].iloc[peak_end] - df['Time'].iloc[peak_start]
    durationsMed.append(duration)
    duration2 = df['Time'].iloc[peak_endMean] - df['Time'].iloc[peak_startMean]
    durationsMean.append(duration2)
    duration3 = df['Time'].iloc[peak_endZ] - df['Time'].iloc[peak_startZ]
    durationsZ.append(duration3)

    ## Get latency of response

    #AUC 3 sec before Stim
    auc1 = metrics.auc(df['Time'].loc[in_between1], df['dFF'].loc[in_between1])
    aucBeforeStim.append(auc1)
    #AUC 5 sec after stim
    auc2 = metrics.auc(df['Time'].loc[in_between2], df['dFF'].loc[in_between2])
    aucAfterStim.append(auc2)
    #AUC during peak Median
    auc3= metrics.auc(df['Time'].iloc[peak_start:peak_end], df['dFF'].iloc[peak_start:peak_end])
    aucDuringPeak.append(auc3)
    #AUC during peak Mean
    auc4= metrics.auc(df['Time'].iloc[peak_startMean:peak_endMean], df['dFF'].iloc[peak_startMean:peak_endMean])
    aucDuringPeakMean.append(auc4)
    ##zDFF calculations
    auc5= metrics.auc(df['Time'].iloc[peak_startZ:peak_endZ], df['zDFF'].iloc[peak_startZ:peak_endZ])
    aucDuringPeakZ.append(auc5)
    auc6= auc1 = metrics.auc(df['Time'].loc[in_between1], df['zDFF'].loc[in_between1])
    aucBeforeStimZ.append(auc6)

# roundList = [baselines, durationsMed, aucBeforeStim, aucAfterStim, aucDuringPeak,
#             aucDuringPeakZ, aucBeforeStimZ]

# for variable in roundList:
#     variable = [round(num, 4) for num in variable]
#     print(variable)

### And make it pretty (Like Emily <3) :))

#Auc Rounds
baselines      = [round(num, 4) for num in baselines]
aucBeforeStim  = [round(num, 4) for num in aucBeforeStim]
aucAfterStim   = [round(num, 4) for num in aucAfterStim]
aucDuringPeak  = [round(num, 4) for num in aucDuringPeak]
aucDuringPeakZ = [round(num, 4) for num in aucDuringPeakZ]
aucBeforeStimZ = [round(num, 4) for num in aucBeforeStimZ]
aucDuringPeakMean = [round(num, 4) for num in aucDuringPeakMean]

#duration rounds
durationsMed   = [round(num, 4) for num in durationsMed]
durationsMean  =  [round(num, 4) for num in durationsMean]
durationsZ     = [round(num, 4) for num in durationsZ]

### OUTPUTS

print("Number of times didn't cross threshold:", no_cross)
print("\nAUC Before stim:", aucBeforeStim)
print("Mean AUC Before stim:",round(np.mean(aucBeforeStim),4))
print("AUC After stim:", aucAfterStim)
print("Mean AUC After stim:",round(np.mean(aucAfterStim),4))
print("AUC During Peak:", aucDuringPeak)
print("Mean AUC During Peak:", round(np.mean(aucDuringPeak),4))

#### Method 1 calculate AUC with threshold as median
print('\n---------"Method 1"---------\n')
print("Method 1: calculate AUC with threshold as median\n")
print("Median = whole trace without firing (dFF below 50 percentile)")
print("Median:",round(medLT50,4))
print("AUC Before stim:", aucBeforeStim)
print("Mean AUC Before stim:",round(np.mean(aucBeforeStim),4))
print("AUC During Peak:", aucDuringPeak)
print("Mean AUC During Peak:", round(np.mean(aucDuringPeak),4))
print("Duration of response:", durationsMed)
print("Mean of response duration:", round(np.mean(durationsMed),4))

print('\n---------"Method 2"---------\n')
print("Method 2: calculate AUC with threshold as mean 3 seconds before stim")
print("Baselines = mean 3 sec before stim\n")
print("Mean whole trace:", mean)
print("Mean whole trace below 50p:", round(meanLT50,4))
print("Baslines:", baselines)
print("Mean of all baselines", round(np.mean(baselines),4))
print("AUC During Peak:", aucDuringPeakMean)
print("Mean AUC During Peak:", round(np.mean(aucDuringPeakMean),4))
print("Duration of response:", durationsMean)
print("Mean of response duration:", round(np.mean(durationsMean),4))

print('\n---------"Method 3"---------\n')
print("Method 3: Do calculations based on z-scored dFF")
print("Threshold = 1.65 SD (SD = 1 in z-scored dFF\n")

print("SD LT50Z:", round(sdLT50Z,4))
print("AUC Before stim Z:", aucBeforeStimZ)
print("Mean AUC Before stim Z:",round(np.mean(aucBeforeStimZ),4))
print("AUC During Peak Z:", aucDuringPeakZ)
print("Mean AUC During Peak Z:", round(np.mean(aucDuringPeakZ),4))
print("Duration of response:", durationsZ)
print("Mean of response duration:", round(np.mean(durationsZ),4))

print('\n---------"Summary"---------\n')

print("Mean AUC:")
print("Method 1:", round(np.mean(aucDuringPeak),4))
print("Method 2:", round(np.mean(aucDuringPeakMean),4))
print("Method 3:", round(np.mean(aucDuringPeakZ),4))

print("\nMean durations:")
print("Method 1:", round(np.mean(durationsMed),4))
print("Method 2:", round(np.mean(durationsMean),4))
print("Method 3:", round(np.mean(durationsZ),4))

# dfexp.to_csv('thresh_outputTest.csv', index=False)

    # print(df['Time'].iloc[peak_start])
    # print(df['Time'].iloc[peak_end])


# MIT License
#
# Copyright (c) 2020 MiscellaneousStuff
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Watch a replay which was made using pylol using the league client."""

from configparser import ConfigParser

from pylol.lib import lol_process
from pylol import run_configs
from pylol.env import lol_env
from pylol.lib import portspicker
from pylol.lib import replay

from absl import flags
from absl import app

flags.DEFINE_string("replay_path", "", "Path to the replay file")
flags.DEFINE_string("config_path", "./config.txt", "File containing directories of GameServer, League client respectively")
flags.DEFINE_string("host", "localhost", "Host for GameServer and league client")
flags.DEFINE_string("players", "Ezreal.BLUE,Ezreal.PURPLE", "NOTE: TEMPORARY")

FLAGS = flags.FLAGS

def main(unused_argv):
    try:
        with open(FLAGS.config_path) as f:
            cfg = ConfigParser()
            cfg.read_string(f.read())
            game_server_dir = cfg.get("dirs", "gameserver")
            client_dir = cfg.get("dirs", "lolclient")
    except:
        raise IOError("Could not open config file: '%s'" % FLAGS.config_path)

    try:
        with open(FLAGS.replay_path) as f:
            replay_info = replay.get_replay_info(f.read())
    except:
        raise IOError("Could not open replay file: '%s'" % FLAGS.config_path)

    try:
        run_config = run_configs.get(game_server_dir=game_server_dir)
        ports = portspicker.pick_contiguous_unused_ports(2)
        client_port = ports[0]
        redis_port = ports[1]
        with run_config.start(replay_path=FLAGS.replay_path,
                                host=FLAGS.host,
                                human_observer=True,
                                players=replay_info["players"],
                                multiplier=replay_info["multiplier"],
                                step_multiplier=1,
                                client_port=client_port,
                                redis_port=redis_port,
                                client_dir=client_dir,
                                map_name=replay_info["map"],
                                cooldowns_enabled=False,
                                manacosts_enabled=False,
                                minion_spawns_enabled=False) as controller:
            controller.connect()
            for _ in range(replay_info["action_count"]):
                controller.observe()
    except KeyboardInterrupt:
        pass

def entry_point():
    app.run(main)

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


###### ESSE SCRIPT ESTA OBSOLETO, CONTINUA AQUI PARA REGISTRAR AS TENTATIVAS DE DIVERSAS TECNICAS ######

###### ESSE SCRIPT TAMBEM CONTEM O CODIGO PARA GERAR AS IMAGENS #######
#TODO: Integrar codigo que gera as imagens ao script principal

# %%imports & func
import os
import pandas as pd
import re
import spacy
import numpy as np
import matplotlib.pyplot as plt

from collections import Counter
from nltk.corpus import stopwords
from nltk.stem.snowball import SnowballStemmer
from sklearn.feature_extraction.text import CountVectorizer
from skmultilearn.problem_transform import BinaryRelevance, LabelPowerset
from sklearn.model_selection import KFold
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import hamming_loss, accuracy_score
import seaborn as sns

def clean_text(msg):
    msg = msg.lower()
    msg = re.sub("[^a-zA-Z]", " ", msg)
    msg = " ".join(msg.split())
    return msg

def stemming(msg):
    msg = clean_text(msg)
    stemmer = SnowballStemmer(language="english")
    wordlist = [
        stemmer.stem(word)
        for word in msg.split()
        if word not in set(stopwords.words("english"))
    ]
    msg = " ".join(wordlist)
    return msg

def lemmatization(msg):
    msg = clean_text(msg)
    doc = nlp(msg)
    tokenlist = [
        token.lemma_ for token in doc if str(token) not in set(nlp.Defaults.stop_words)
    ]
    msg = " ".join(tokenlist)
    return msg

def word_freq(wordlist, n):
    big_sen = ""

    for sen in wordlist:
        big_sen += sen

    return Counter(big_sen.split()).most_common(n)

STOPWORDS = [
    "a",
    "e",
    "n",
    "s",
    "m",
    "o",
    "br",
    "ls",
    "www",
    "com",
    "fot",
    "cs",
    "hayasa",
    "apollo",
]

# %%Parameters part 1
norm = lemmatization  # stemming, lemmatization
stopwords_cond = True  # True, False

# %%Adding stopwords
nlp = spacy.load("en_core_web_sm")

if stopwords_cond:
    for word in nlp.Defaults.stop_words:
        lex = nlp.vocab[word]
        lex.is_stop = True

    stopwords.words("english").extend(STOPWORDS)

    nlp.Defaults.stop_words |= set(STOPWORDS)

# %%Loading dataset
dataset = pd.read_excel("Datasets/Dataset OneHot.xlsx")
labels_dataframe = dataset.iloc[:, 1:]

# %%Visualizing classes
sns.set()
sns.set_style("darkgrid")
plt.subplots(figsize=(10, 9))

sum_msgs = labels_dataframe.sum(axis=0).sort_values(ascending=False)

ax = sns.barplot(y=labels_dataframe.columns.values, x=sum_msgs, color="#B1587E")

for i, val in enumerate(sum_msgs):
    ax.text(val + 30, i, val, color="black", va="center", fontsize=10)

plt.ylabel("Ato de Fala", fontsize=13)
plt.xlabel("Contagem", fontsize=13)
plt.title("Contagem de mensagens por Ato de Fala", fontsize=16)

plt.savefig("cont msgs.png", dpi=300)

# %%Visualizing classes
sns.set_style("white")

count_lbl = (
    pd.DataFrame(labels_dataframe.sum(axis=1).sort_values(ascending=False))
    .reset_index()
    .groupby(0)
    .count()
    .reset_index()
    .rename(columns={0: "num_lbl", "index": "count"})
)

plt.subplots(figsize=(10, 9))
ax = sns.barplot(x=count_lbl["num_lbl"], y=count_lbl["count"], color="#833788")

for i, num_lbl, count in count_lbl.itertuples():
    ax.text(i, count + 30, count, color="black", ha="center", fontsize=11)

plt.xlabel("Quantidade de labels na mensagem", fontsize=13)
plt.ylabel("Número de mensagens", fontsize=13)
plt.title("Número de mensagens por quantidade de labels", fontsize=16)

# plt.savefig('count lbl.png', dpi=300)
# %%Visualizing classes
sns.set_style("ticks")

len_msgs = [len(msg) for msg in dataset["msgContent"]]

plt.subplots(figsize=(10, 9))
sns.distplot(len_msgs, hist=False, color="black")
plt.xlabel("Tamanho da mensagem (quantidade de caracteres)", fontsize=13)
plt.title("Histograma de frequencia do tamanho das mensagens", fontsize=16)

plt.savefig("hist_freq.png", dpi=300)
# %%Visualizing classes

len_msgs = [len(msg) for msg in dataset["msgContent"] if len(msg) <= 500]

plt.subplots(figsize=(10, 9))
sns.distplot(len_msgs, bins=20, kde=False, hist_kws=dict(alpha=1), color="#635751")
plt.xlabel("Tamanho da mensagem (quantidade de caracteres)", fontsize=13)
plt.title(
    "Histograma do tamanho das mensagens com tamanho menor ou igual a 500", fontsize=16
)

plt.savefig("hist_tam_msgs.png", dpi=300)
# %%Corpus creation
corpus = [norm(msg) for msg in list(dataset["msgContent"])]

# %%Parameters part 2
method = BinaryRelevance  # BinaryRelevance, LabelPowerset
classifier = LogisticRegression  # LogisticRegression, SVC, GaussianNB
max_iterations = 40
max_ft = 2000
k = 5

# %%Creating model & splitting dataset

# Creating the Bag of Words model
cv = CountVectorizer(max_features=max_ft)
X = cv.fit_transform(corpus)

y = labels_dataframe.values

acc_array = []
hamm_loss_array = []

# Splitting the dataset into training and test sets
kf = KFold(n_splits=k)

for train_index, test_index in kf.split(X):
    X_train, X_test, y_train, y_test = (
        X[train_index],
        X[test_index],
        y[train_index],
        y[test_index],
    )

    cf = method(classifier(max_iter=max_iterations, random_state=42))
    cf.fit(X_train, y_train)
    y_pred = cf.predict(X_test)

    acc_array.append(accuracy_score(y_test, y_pred))
    hamm_loss_array.append(hamming_loss(y_test, y_pred))

acc = np.mean(acc_array)
hamm_loss = np.mean(hamm_loss_array)

# -------

my_msg = dataset.iloc[4562]["msgContent"]

my_msg_clean = clean_text(my_msg)
my_msg_stem = stemming(my_msg)
my_msg_lemma = lemmatization(my_msg)

wordlist = [
    word for word in my_msg_clean.split() if word not in set(stopwords.words("english"))
]

msg_stpwd = " ".join(wordlist)

doc = nlp(msg_stpwd)
tokenlist = [token.lemma_ for token in doc]
msg_lem = " ".join(tokenlist)

my_msg = list([my_msg])
my_X = cv.transform(my_msg)

my_pred = cf.predict(my_X)

my_pred = my_pred.todense()

# Printing used parameters
print("\n\033[4mParameters:\033[0m\n")
print(f"Normalization: {norm.__name__}")
print(f"\nMethod: {method.__name__}")
print(f"Classifier: {classifier.__name__}")
print(f"Max iterations: {max_iterations}")
print(f"Max features: {max_ft}")
print(f"k: {k}")

# Printing results
print("\n\033[4mMetrics:\033[0m\n")
print(f"Accuracy: {acc:.2%}")
print(f"Hamming Loss: {hamm_loss:.2%}")


# Scraping Articles

# Import dependencies
from splinter import Browser
from bs4 import BeautifulSoup
import pandas as pd
import datetime as dt

def scrape_all():
    # Initiate headless driver for deployment
    # headless=True means scraping will be done behind the scenes and no webpage will open to visually watch
    browser = Browser("chrome", executable_path="chromedriver", headless=True)

    # Set news title and paragraph variables, function will return two values. Tells Python to use mars_news function to pull this data.
    news_title, news_paragraph = mars_news(browser)

    # Run all scraping functions and store results in dictionary
    data = {
        "news_title": news_title,
        "news_paragraph": news_paragraph,
        "featured_image": featured_image(browser),
        "facts": mars_facts(),
        "hemispheres": mars_hemisphere_images(browser),
        "last_modified": dt.datetime.now()
    }
    print(data)

    # Stop webdriver and return data
    browser.quit()
    return data

# Set the executable path and initialize the chrome browser in splinter
#executable_path = {'executable_path': '/usr/local/bin/chromedriver'}
#browser = Browser('chrome', **executable_path)
# **executable_path is unpacking the dictionary we’ve stored the path in.

# Declare and define fucntion
def mars_news(browser):
    #Scrape Mars News

    # Visit the mars nasa news site
    url = 'https://mars.nasa.gov/news/'
    browser.visit(url)

    # Optional delay for loading the page
    browser.is_element_present_by_css("ul.item_list li.slide", wait_time=1)
    # Searching for elements with a specific combination of tag (ul and li) and attribute (item_list and slide).
    # Tell browser to wait one second before searching for components. The optional delay is useful because
    #sometimes dynamic pages take a little while to load, especially if they are image-heavy.

    # Set up the HTML Parser
    html = browser.html
    news_soup = BeautifulSoup(html, 'html.parser')

    #Add try/except for error handling
    try:
        # Assigned slide_elem as the variable to look for the <ul /> tag and its descendent (the other tags within the
        # <ul /> element), the <li /> tags. This is the parent element, it holds all of the other elements within it,
        # we reference it when we want to filter search results even further. The . is used for selecting classes, such as
        # item_list, so the code 'ul.item_list li.slide' pinpoints the <li /> tag with the class of slide and the
        # <ul /> tag with a class of item_list. CSS works from right to left, such as returning the last item on the list
        # instead of the first. Because of this, when using select_one, the first matching element returned will be
        # a <li /> element with a class of slide and all nested elements within it.
        slide_elem = news_soup.select_one('ul.item_list li.slide')

        # Use the parent element to find the first `a` tag and save it as `news_title`
        news_title = slide_elem.find("div", class_='content_title').get_text()

        # Use the parent element to find the paragraph text
        news_p = slide_elem.find('div', class_="article_teaser_body").get_text()

    except AttributeError:
        return None, None

    return news_title, news_p

# Scraping Images

# Declare and define function
def featured_image(browser):

    # Visit URL
    url = 'https://www.jpl.nasa.gov/spaceimages/?search=&category=Mars'
    browser.visit(url)

    # Find and click the full image button
    full_image_elem = browser.find_by_id('full_image')
    full_image_elem.click()

    # Find the more info button by searching for text and click it
    browser.is_element_present_by_text('more info', wait_time=1)
    more_info_elem = browser.links.find_by_partial_text('more info')
    more_info_elem.click()

    # Parse the resulting html with soup
    html = browser.html
    img_soup = BeautifulSoup(html, 'html.parser')

    try:
        # Find the relative image url
        img_url_rel = img_soup.select_one('figure.lede a img').get("src")
        # tell BeautifulSoup to look inside the <figure class=”lede” /> tag for an <a /> tag, and then look within
        # that <a /> tag for an <img /> tag.
        # Pull the link of the image by pointing BeautifulSoup to where the image will be, instead of grabbing the URL
        # directly. This way, when NASA updates its image page, the code will still pull the most recent image.

    except AttributeError:
        return None

    # Use the base URL to create an absolute URL
    img_url = f'https://www.jpl.nasa.gov{img_url_rel}'

    return img_url

# Mars Facts
def mars_facts():

    try:
        # Scrape HTML table and store in new df
        # The Pandas function read_html() specifically searches for and returns a list of tables found in the HTML.
        # By specifying an index of 0, we’re telling Pandas to pull only the first table it encounters.
        df = pd.read_html('http://space-facts.com/mars/')[0]

    except BaseException:
        return None

    # Assign columns to the new DataFrame for additional clarity
    df.columns=['Description', 'Mars']

    # Turn the Description column into the DataFrame’s index. inplace=True means that the updated index will remain
    # in place, without having to reassign the DataFrame to a new variable.
    df.set_index('Description', inplace=True)

    # Convert stored df back into HTML format so it can be added to a website
    return df.to_html(classes="table table -striped")

# CHALLENGE
# Reviewed speed run for assistance with function creation

# Store Mars Hemisphere Image links
def mars_hemisphere_images(browser):

    #create list
    hemisphere_image_urls = []

    #Assign mars image website to url variable
    url = 'https://astrogeology.usgs.gov/search/results?q=hemisphere+enhanced&k1=target&v1=Mars'
    #visit site
    browser.visit(url)

    #retrieve list of hemisphere links
    #links = browser.find_by_css('a.product-item h3', wait_time=1)

    #loop through links
    for index in range (4):

        #find element link and click
        browser.find_by_css('a.product-item h3')[index].click()
        # Call scrape_hemisphere_images function and store results
        hemisphere_data = scrape_hemisphere_images(browser.html)
        #add image and title to list
        hemisphere_image_urls.append(hemisphere_data)

        #navigate back for next image link
        browser.back()

    return hemisphere_image_urls

#scrape hemisphere images
def scrape_hemisphere_images(html_text):

    #parse html text
    hemispheres_soup = BeautifulSoup(html_text, "html.parser")

    #Try to scrape image and title
    try:
        hemisphere_title = hemispheres_soup.find("h2", class_="title").get_text()
        image_link = hemispheres_soup.find("a", text="Sample").get("href")
    #return nothing if error occcurs
    except AttributeError:
        hemisphere_title = None
        image_link = None

    #create dictionary with stored image and title
    hemispheres = {
        "title": hemisphere_title,
        "image_url": image_link
    }

    return hemispheres

# Tell Flask to run
if __name__ == "__main__":
    # If running as script, print scraped data
    print(scrape_all())


from numpy import*
a=int(input('           Enter the first number of fabonachi sequence: '))
b=int(input('           Enter the second number of fabonachi sequence: '))
l=int(input('           enter the number of terms to be generated: '))
print('\n\n\n')
arr=zeros(l,longdouble)
arr[0]=longdouble(a)
arr[1]=longdouble(b)
for i in range(2,l):
    arr[i]=arr[i-1]+arr[i-2]
print('         The fabonachi sequence generated from given starting numbers is:')
for j in range(0,l):
    print('         ',arr[j],end=' ')


"""
Developed By: JumpShot Team
Written by: riscyseven
"""

from PyQt6.QtWidgets import QDialog, QMessageBox
from PyQt6 import uic
from editor.proptab.fileseldialog import FileSelWidget

from gm_resources import resourcePath
from attr import CompAttr

class GlobalDirectory(QDialog):
    def __init__(self, dirName, parent=None):
        super().__init__(parent)
        path = resourcePath("src/editor/globaldirectory.ui")
        uic.loadUi(path, self) # Load the .ui file
        self.fileDialog = FileSelWidget(CompAttr.DRSAVE, self._fileSelected, dirName, self)
        self.verticalLayout.addWidget(self.fileDialog)
        self.setWindowTitle("Set Global File Output Location")
        self.pushButton.clicked.connect(self._setClicked)
        self.dir = dirName

    def _fileSelected(self, dirName):
        self.dir = dirName

    def _setClicked(self):
        if (QMessageBox.warning(self, "Are you sure?", "This action will:\n"
            "   1. Change the root directory of each display component\n"
            "   2. Change all output file names to its component names\n"
            "Do you want to proceed?", QMessageBox.StandardButton.Ok |
                 QMessageBox.StandardButton.Cancel) == QMessageBox.StandardButton.Cancel):
                 self.dir = ""
        self.close()

    def getDirectory(self) -> str:
        return self.dir


def find_min(list):
    min = list[0]
    for item in list:
        if item< min:
            min = item
    return min

def is_anagram2(s1, s2):
    if sorted(s1) == sorted(s2):
        return True
    return False


from fluent import FnLEFluent
from opt.function import CollisionFn
from utils import *
from openravepy import *
import ctrajoptpy
import numpy as np
import time

# If True, verify that caching produces equivalent results to
# computation. If False, actually do caching (return cached value).
CACHING_DEBUG = False

class NotObstructs(FnLEFluent):
    # def __init__(self, env, hl_action, robot, priority, traj, obj, obj_loc, dsafe=0.05):
    def __init__(self, env, hl_action, robot, priority, traj, obj, obj_loc=None, dsafe=0.05):
        self.env = env
        self.plotting_env = hl_action.hl_plan.env
        self.hl_action = hl_action
        self.traj = traj
        self.obj = obj
        self.obj_loc = obj_loc
        self.robot = robot
        self.priority = priority
        self.name = "NotObstructs"
        self.K = self.hl_action.K
        self.T = self.hl_action.T
        self.cc = ctrajoptpy.GetCollisionChecker(env)
        self.dsafe = dsafe
        self.cache = {}
        self.allow_early_converge = True

    def pre(self):
        traj = self.traj

        g = lambda x: self.collisions(x) # function inequality constraint g(x) <= 0
        obj_loc_list = []
        if self.obj_loc is not None:
            obj_loc_list = [self.obj_loc for i in range(self.T)]
        self.fn = CollisionFn([self.traj] + obj_loc_list, g)

    # TODO: compute collisions properly
    # @profile
    def collisions(self, traj):
        flattened = tuple(traj.round(5).flatten())
        v_check, j_check = None, None
        if flattened in self.cache:
            if CACHING_DEBUG:
                v_check, j_check = self.cache[flattened]
            else:
                return self.cache[flattened]

        env = self.env
        T = self.T
        K = self.K

        # ensure that there's gradient information outside dsafe
        self.cc.SetContactDistance(self.dsafe + .1)

        handles = []

        if self.obj_loc is not None:
            val = np.zeros((2*self.T, 1))
            jac = np.zeros((2*self.T, traj.size))
        else:
            val = np.zeros((self.T, 1))
            jac = np.zeros((self.T, traj.size))
        # if self.obj_loc is not None:
        #     self.obj.set_pose(env, self.obj_loc.set_value())

        if self.priority == 1:
            lst = [0, T-1]
        elif self.priority == 2:
            # since priority 1 was already run, don't need to recheck end states
            lst = range(1, T-1)
        else:
            raise NotImplementedError
        for t in lst:
            # xt = self.traj.set_value()[K*t:K*(t+1)]
            # xt = traj[:,t:t+1]
            xt = traj[K*t:K*(t+1)]
            self.robot.set_pose(env, xt)
            ot = None
            if self.obj_loc is not None:
                ot = traj[K*(t+T):K*(t+1+T)]
                self.obj.set_pose(env, ot)
            collisions = self.cc.BodyVsAll(self.robot.get_env_body(env))

            col_val, robot_jac, obj_jac = self.calc_grad_and_val(xt, ot, collisions)
            if robot_jac is not None:
                val[t], jac[t, K*t:K*(t+1)] = col_val, robot_jac
                if self.obj_loc is not None:
                    val[t+T], jac[t+T, K*(t+T):K*(t+1+T)] = col_val, obj_jac
                    # cross terms
                    jac[t, K*(t+T):K*(t+1+T)] = obj_jac
                    jac[t+T, K*t:K*(t+1)] = robot_jac

        self.plotting_env.UpdatePublishedBodies()
        handles = []

        if CACHING_DEBUG:
            assert v_check is None or np.allclose(v_check, val, atol=1e-4)
            assert j_check is None or np.allclose(j_check, jac, atol=1e-4)
        self.cache[flattened] = (val, jac)
        return (val, jac)

    # @profile
    def calc_grad_and_val(self, xt, ot, collisions):
        val = -1*float("inf")
        robot_grad = None
        obj_grad = None
        for c in collisions:
            linkA = c.GetLinkAParentName()
            linkB = c.GetLinkBParentName()

            if linkA == self.robot.name and linkB == self.obj.name:
                ptRobot = c.GetPtA()
                ptObj = c.GetPtB()
            elif linkB == self.robot.name and linkA == self.obj.name:
                ptRobot = c.GetPtB()
                ptObj = c.GetPtA()
            else:
                continue

            ptRobot[2] = 1.01
            ptObj[2] = 1.01

            distance = c.GetDistance()
            normal = c.GetNormal()

            # plotting
            self.plot_collision(ptRobot, ptObj, distance)

            # if there are multiple collisions, use the one with the greatest penetration distance
            if self.dsafe - distance > val:
                val = self.dsafe - distance

                robot_grad = np.dot(-1 * normal[0:2], self.calc_jacobian(np.transpose(ptObj), xt))
                if ot is not None:
                    obj_grad = np.dot(normal[0:2], self.calc_jacobian(np.transpose(ptRobot), ot))

        return val, robot_grad, obj_grad

    def plot_collision(self, ptA, ptB, distance):
        handles = []
        if not np.allclose(ptA, ptB, atol=1e-3):
            if distance < 0:
                handles.append(self.plotting_env.drawarrow(p1=ptA, p2=ptB, linewidth=.01,color=(1,0,0)))
            else:
                handles.append(self.plotting_env.drawarrow(p1=ptA, p2=ptB, linewidth=.01,color=(0,0,0)))
        self.hl_action.add_plot_handles(handles)

    def calc_jacobian(self, pt, x0):
        jac = np.zeros((2,3))
        r = pt[0:2] - x0[0:2, 0]
        jac[0,0] = 1
        jac[1,1] = 1
        jac[0,2] = -r[1]
        jac[1,2] = r[0]
        # return np.matrix(jac)
        return jac

    def params_to_resample(self):
        # resample ObjLoc, Start Robot Pose, and End Robot Pose
        return filter(lambda p: p is not None and p.is_resampled, [self.obj_loc, self.hl_action.start, self.hl_action.end])


import gym

env = gym.make('Taxi-v2')
env.reset()

for _ in range(1000):
    env.render()

    # action = env.action_space.sample()

    action = input("next action: ")
    action = int(action)

    next_state, reward, done, _ = env.step(action)

    print (next_state, reward)


# Лабораторная работа № 12, вариант № 3, Белинский В. А., группа № 2022-ФГиИБ-ПИ-1см

import math

with open("data.csv") as file:
    next(file)
    for row in file:
        rows_data = file.readlines()

def getting_list_mens(rows_data, min_value_age, max_value_age, gender_person):
    result_rows = []
    for row in rows_data:
        rows = row.rstrip().split(",")
        min_value_age = float(min_value_age)
        max_value_age = float(max_value_age)
        age = row.rstrip().split(',')[6]
        for i in age:
            if i == "":
                age.remove(i)
            age = float(age)
            age = math.floor(age)
            if age >= min_value_age and age <= max_value_age and rows[5] == gender_person:
                result_rows += [rows[3] + ' ' + rows[4] + ', ' + rows[6] + ', ' + rows[2]]
                break
    return result_rows


import re

from pyutils import *

def manhattan(a, b):
    return abs(a[0]-b[0])+abs(a[1]-b[1])

def parse(lines):
    data = []
    for line in lines:
        coords = list(int(n) for n in re.findall(r'-?\d+', line))
        sensor, beacon = (coords[0], coords[1]), (coords[2], coords[3])
        distance = manhattan(sensor, beacon)
        data.append((sensor, beacon, distance))
    return data

# @expect({'test': 26})
def solve1(data):
    # Y = 10
    Y = 2_000_000
    excluded = set()
    for sensor, _, distance in data:
        dy = abs(sensor[1]-Y)
        if distance >= dy:
            excluded.update((x, Y) for x in range(
                sensor[0] - distance+dy, sensor[0]+distance-dy+1, 1))
    return len(excluded.difference(set(b for _, b, _ in data)))

# @expect({'test': 56000011})
def solve2(data):
    # LIMIT = 20
    LIMIT = 4_000_000
    beacons = set(b for _, b, _ in data)

    def valid(pos):
        return 0 <= pos[0] <= LIMIT and 0 <= pos[1] <= LIMIT and pos not in beacons and all(manhattan(pos, s) > d for s, _, d in data)

    for sensor, _, distance in data:
        for dy in range(distance+2):
            for pos in [(sensor[0]+dy, sensor[1]+distance+1-dy),
                        (sensor[0]+dy, sensor[1]-distance-1+dy),
                        (sensor[0]-dy, sensor[1]+distance+1-dy),
                        (sensor[0]-dy, sensor[1]-distance-1+dy),
                        ]:
                if valid(pos):
                    return pos[0]*4_000_000+pos[1]
    return None


#Python Program to Accept Three Digits and Print all Possible Combinations from the Digits
a=int(input("Enter 1st number:"))
b=int(input("Enter 2nd number:"))
c=int(input("Enter 3rd number:"))

x=[]
x.append(a)
x.append(b)
x.append(c)

for i in range(0,3):
    for j in range(0,3):
        for k in range(0,3):
            if (i!=j & j!=k & k!=i):
                print(x[i],x[j],x[k])


def shell_sort(arr):
    n = len(arr)
    gap = n // 2 # 초기 gap 설정

    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            # 부분적으로 정렬된 리스트의 작은 값들이 앞에 오도록 세부 정렬
            while j >= gap and arr[j-gap] > temp:
                arr[j] = arr[j-gap]
                j -= gap
            arr[j] = temp # 확정 위치에 하나씩 넣어줌
        gap //= 2 # gap 감소

    return arr

print(shell_sort([5,1,3,2,4]))


#!/usr/bin/python3
from pprint import pprint

debug = False
file = 'ldirectord.cf'

a = open(file, 'r')
itemList = a.readlines()
a.close()

riga = []
struttura = {}
linea = ""

# leggo dati
for line in itemList:
   riga=line.lstrip("\t ").rstrip("\n").split("=")
   if ( riga[0] == "virtual" ):
      pool = riga[1]
      struttura[ pool ] = []
   elif ( riga[0] == "real" ):
      struttura[ pool ].append( riga[1].split()[0] )

#pprint( struttura )

#genero output
for chiave, valore in struttura.items():
   linea = ""
   linea += chiave +  ","
   for real in sorted( valore ):
      linea +=  real + ","

   print( linea )


#Dieses Programm berechnet einen beliebigen Modulo einer beliebigen Zahl ohne den Modulo-Operator
#in Python zu werdenen.

#In der Variable n wird eine Zahl gespeichert, durch die später modulo gerechnet werden soll
n = int(input("Bitte geben Sie eine Zahl ein, die mit Modulo berechnet werden soll:"))

#In der Variable mod wird eine Zahl gespeichert, mit der geteilt wird.
mod = int(input("Bitte geben sie eine beliebige Zahl für den Modulo-Wert an:"))

#Fallunterscheidung: N ist kleiner als Null = Negativ und mod ist größer als Null = Positiv
if n < 0 and mod > 0:
    while n <= 0:
        n = n + mod
    else:
        print ("Der Rest der anhand ihrer Zahlenauswahl berechnet wurde beträgt", (n))
#1. Wenn n Negativ ist und Mod Positiv, dann wird in der Variablen n solange modulo addiert, bis n größer 0.
#Dieses n wird ausgegeben.

#Fallunterscheidung: N ist größer als Null = Positiv und mod ist kleiner als Null = Negativ
elif n > 0 and mod < 0:
    while n > 0:
        n = n + mod
    else:
        print ("Der Rest der anhand ihrer Zahlenauswahl berechnet wurde beträgt", (n))
#Siehe Kommentar 1.

#Fallunterscheidung: Beide Variablen n und mod sind positiv
elif n > 0 and mod > 0:
    while n >= mod:
        n = n - mod
    else:
        print ("Der Rest der anhand ihrer Zahlenauswahl berechnet wurde beträgt", (n))
#2. Wenn n Positiv ist und Mod Positiv, dann wird mod solange von n abgezogen, bis n kleiner als mod ist.
#Dieses n wird augegeben.

#Fehlerbehandlung: Error bei mod = 0. Durch Null teilen nicht erlaubt.
elif mod == 0:
        print ("Nicht durch 0 teilen!")

#Fallunterscheidung: N ist kleiner als Null = Negativ und mod ist kleiner als Null = Negativ
else:
    while n <= mod:
        n = n - mod
    else:
        print ("Der Rest der anhand ihrer Zahlenauswahl berechnet wurde beträgt", (n))
#Siehe Kommentar 2.


# Zadacha 1:
# Napishite funkciyu, kotoraya menyaet znachenie globalnoy peremennoy.

varr = 10
print(varr)

def change_var():
    global varr
    varr = varr + 1

change_var()
print(varr)

# Zadacha 2:
# Napishite funkciyu dlya togo, chtobi poschitat znachenie factoriala chisla, kotoroe peredaetsya
# argumentom.

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

print(factorial(5))

def factorial_num (x):
    total = 1
    if x == 0 or x == 1:
        x = 1
        print(x)
    elif x > 1:
        for num in range(x):
            num += 1
            total *= num
        print(total)
    else:
        pass

factorial_num(5)

# Zadacha 3:
# Naydite naybolshee znachenie v spiske s pomoshyu rekursii.

def recursion():
    list_1 = [0, 2, 3, 4, 9]
    list_2 =[]
    for x in list_1:
        if x == 0 or x == 1:
            x = 1
            list_2.append(x)
        elif x > 1:
            total = 1
            j = 0
            while x > j:
                total *= x
                x -= 1
            list_2.append(total)
        else:
            pass
    y = max(list_2)
    i = 1
    while y > i:
        y = y // i
        i += 1
    print("Найбільше значення у списку -", str(y) + '!')

recursion()


from collections import deque
# bfs를 하기 위한 첫 번째

def BFS(i,j):
    queue = deque() # 큐를 deque()으로 만들어준다.
    queue.append((i,j)) # 들어가는 자리를
    d=[(-1,0),(0,-1),(1,0),(0,1)] # 좌표를 상하좌우로 델타탐색 한다.
    cnt=1 # 들어갈 때 cnt 하나 해준다.

    while queue: # 큐가 빌 때 까지 해준다.
        y,x = queue.popleft() # 맨 왼쪽 값 뽑고 리스트에서 삭제
        for dy,dx in d : # for _ in range(4) 델타 탐색 상하좌우 하는 느낌으로
            Y,X = y+dy, x+dx # 델타 탐색 해주고,
            if (0<= Y < M) and (0 <= X < N) and graph[Y][X] == 0: # 범위 안에 있거나, 가보지 않았으면
                graph[Y][X] = 1 # 1 넣어주고
                queue.append((Y,X)) # 해당 좌표 넣어주고
                cnt +=1 # 1 더해주고..

    return cnt # 끝나면 count한 값

M,N,K = map(int,input().split())
graph = [[0]*N for _ in range(M)]

for _ in range(K):
    x1,y1,x2,y2 = map(int,input().split())
    for i in range(y1,y2):
        for j in range(x1,x2):
            graph[i][j] = 1

result = []
for i in range(M):
    for j in range(N):
        if graph[i][j] == 0: # 공백이면,
            graph[i][j] = 1 # 1을 칠해주고
            result.append(BFS(i,j)) # bfs 돌아준다.

print(len(result))
print(*sorted(result))


import typing
from typing import Callable

import pytest
from typing_extensions import Literal

from typeguard._union_transformer import compile_type_hint, type_substitutions

eval_globals = {"Callable": Callable, "Literal": Literal, "typing": typing}
eval_globals.update(type_substitutions)

@pytest.mark.parametrize(
    "inputval, expected",
    [
        ["str | int", "Union[str, int]"],
        ["str | int | bytes", "Union[str, int, bytes]"],
        ["str | Union[int | bytes, set]", "Union[str, int, bytes, Set]"],
        ["str | int | Callable[..., bytes]", "Union[str, int, Callable[..., bytes]]"],
        ["str | int | Callable[[], bytes]", "Union[str, int, Callable[[], bytes]]"],
        [
            "str | int | Callable[[], bytes | set]",
            "Union[str, int, Callable[[], Union[bytes, Set]]]",
        ],
        ["str | int | Literal['foo']", "Union[str, int, Literal['foo']]"],
        ["str | int | Literal[-1]", "Union[str, int, Literal[-1]]"],
        ["str | int | Literal[-1]", "Union[str, int, Literal[-1]]"],
        [
            'str | int | Literal["It\'s a string \'\\""]',
            "Union[str, int, Literal['It\\'s a string \\'\"']]",
        ],
        [
            "typing.Tuple | typing.List | Literal[-1]",
            "Union[Tuple, List, Literal[-1]]",
        ],
        ["tuple[int, ...]", "Tuple[int, ...]"],
    ],
)
def test_union_transformer(inputval: str, expected: str) -> None:
    code = compile_type_hint(inputval)
    evaluated = eval(code, eval_globals)
    evaluated_repr = repr(evaluated)
    evaluated_repr = evaluated_repr.replace("typing.", "")
    evaluated_repr = evaluated_repr.replace("typing_extensions.", "")
    assert evaluated_repr == expected


with open("input.txt") as file:
    text = file.read().split("\n")

bag_structure = {}

for line in text:
    contains = []
    words = line.split()
    bag_name = " ".join(words[:2])
    if "no other" not in line:
        i = 4
        for i in range(4, len(words), 4):
            name = f"{words[i + 1]} {words[i + 2]}"
            num = int(words[i])
            contains.append((name, num))
    bag_structure[bag_name] = contains

has_gold_mem = {}
bags_in_bag_mem = {}

def has_gold_bag(b_name):
    if b_name in has_gold_mem:
        return has_gold_mem[b_name]
    bs = bag_structure[b_name]
    if len(bs) == 0:
        return False
    for b in bs:
        if b[0] == "shiny gold":
            return True
    for b in bs:
        if b[0] not in has_gold_mem:
            check = has_gold_bag(b[0])
        else:
            check = has_gold_mem[b[0]]
        if check:
            return True
    return False

def bags_in_bag(b_name: str):
    if b_name in bags_in_bag_mem:
        return bags_in_bag_mem[b_name]
    bs = bag_structure[b_name]
    if len(bs) == 0:
        return 0
    b_total = 0
    for b in bs:
        if b[0] not in bags_in_bag_mem:
            n_in_bag = bags_in_bag(b[0])
        else:
            n_in_bag = bags_in_bag_mem[b[0]]
        b_total += b[1] + b[1] * n_in_bag
    return b_total

num_containing_gold = 0
for bag in bag_structure.keys():
    num_containing_gold += has_gold_bag(bag)
print(num_containing_gold)

print(bags_in_bag("shiny gold"))


from collections import deque
from trees import build_binary_tree, is_leaf_node

def find_path(root, sequence):
    """
    Given a binary tree and a number sequence, find if the sequence is present as a
    root-to-leaf path in the given tree.
    """
    seq_q = deque(sequence)

    def helper(root, seq):
        if root.val is None:
            return
        if is_leaf_node(root) and len(seq) == 1 and seq[0] == root.val:
            return True
        msd = seq.popleft()
        if msd == root.val:
            leftret = helper(root.left, seq)
            seq.appendleft(msd)
            rightret = helper(root.right, seq)
            return leftret or rightret
        else:
            return False

    return helper(root, seq_q)

if __name__ == '__main__':
    root = build_binary_tree([1, 0, 1, None, 1, 6, 5])
    print(find_path(root, [1, 1, 6]))


"""Create the application's database.

Run this once after installing the application::

    python -m pygall.scripts.setup development.ini [-d|--drop]
"""
import logging
import sys
import os

from pyramid.paster import get_app
import transaction

from pygall import models

def main():
    if len(sys.argv) < 2:
        sys.exit("Usage: python -m pygall.scripts.setup INI_FILE#section [-d|--drop]")
    args = sys.argv[1].split('#')
    ini_file = args[0]
    section = args[1] if len(args)>1 else 'PyGall'
    logging.config.fileConfig(ini_file)
    log = logging.getLogger(__name__)
    app = get_app(ini_file, section)
    settings = app.registry.settings

    if len(sys.argv) > 2 and sys.argv[2] in ['-d', '--drop']:
        log.info("Dropping tables")
        models.Base.metadata.drop_all()
    # Abort if any tables exist to prevent accidental overwriting
    for table in models.Base.metadata.sorted_tables:
        log.debug("checking if table '%s' exists", table.name)
        if table.exists():
            raise RuntimeError("database table '%s' exists" % table.name)

    log.info("Creating tables")
    models.Base.metadata.create_all()

    log.info("Inserting data")
    sess = models.DBSession()
    # insert data here #
    transaction.commit()

    log.info("Generating auth.cfg file")
    with open(settings['auth_cfg'], 'w') as f:
        f.write("# This file contains the credentials of users allowed to\n" \
                "# access to the PyGall photo gallery.\n" \
                "# Currently pygall contains only one group: 'admin'.\n" \
                "# The format of each line should look like:\n" \
                "# 'username:password[:group]'\n" \
                "admin:N5rIuAWOHGycs:admin\n" \
                "guest:Z7TjkT9L.lUAM\n")

if __name__ == "__main__":
    main()


import random as rd
import datetime
import time

# PLAYER 1 ATTACKING PLAYER 2 (CHECK BEFOREHAND THEY HAVE ENOUGH LIFE)
def combat(player1, player2):
    if player1.cannot_attack == True or player2.immune == True or player2.sneak == True:
        print('Player 1 cannot attack, so no combat!')
        return None

    # If a player is frozen, then they automatically lose a life and are unfrozen
    if player2.cannot_attack == True:
            player2.hp -= 1
            player2.cannot_attack = False
            print('Player 2 was frozen!')
            return True
    player1_combat = rd.randint(1, 20)
    player2_combat = rd.randint(1, 20)
    player1_combat += player1.attack_bonus
    player2_combat += player2.defense_bonus
    if player1_combat > player2_combat:
        player2.hp -= 1
        print('Player 1 wins!')
        return True
    elif player2_combat > player1_combat:
        player1.hp -= 1
        print('Player 2 wins!')
        return False
    else:
        print("It's a tie!")
        return None
    return None

class Player:
    # Initialize the player

    def __init__(self):
        self.hp = 20
        self.inventory = []

        # Keep track of capabilites for fighting
        self.cannot_attack = False
        self.cannot_attack_time = None

        # To keep track of immune
        self.immune = False
        self.time_of_immune = None

        self.attack_bonus = 0
        self.defense_bonus = 0

class Wizard(Player):
    def __init__(self):
        Player.__init__(self)
        self.cast_freeze = False
        self.sneak = False
        self.cast_freeze_date = None

    def fireball(self, player2):
        self.attack_bonus += 2
        combat(self, player2)
        self.attack_bonus -= 2

    def freeze(self, player2):
        if not self.cast_freeze:
            player2.cannot_attack = True
            player2.cannot_attack_time = time.time()
            self.cast_freeze = True
            self.cast_freeze_date = datetime.datetime.now().date()
        else:
            print("You cannot cast that again for another day.")

    def check(self):
        if self.immune == True:
            # Measures in seconds
            if self.time_of_immune <= time.time() - 1800:
                self.immune = False
                self.time_of_immune = None

        if self.cannot_attack == True:
            # Measures in seconds
            if self.cannot_attack_time <= time.time() - 1800:
                self.cannot_attack = False
                self.cannot_attack_time = None

        if self.cast_freeze == True:
            if datetime.datetime.now().date() != self.case_freeze_date:
                self.cast_freeze = False
                self.cast_freeze_date = None

class Warrior(Player):
    def __init__(self):
        Player.__init__(self)
        self.defensive_maneuver = False
        self.defensive_maneuver_time = None
        self.cast_defensive_maneuver = False
        self.defensive_maneuver_cast_time = None
        self.sneak = False

    def rend(self, player2):
        self.attack_bonus += 2
        combat(self, player2)
        self.attack_bonus -= 2

    def defensive_manuever(self):
        if self.cast_defensive_maneuver == False:
            self.defense_bonus += 2
            self.defensive_maneuver = True
            self.cast_defensive_maneuver = True
            self.defensive_maneuver_time = time.time()
            self.defensive_maneuver_cast_time = datetime.datetime.now().date()
        else:
            print("You cannot cast that again for another day.")

    def check(self):
        if self.immune == True:
            # Measures in seconds
            if self.time_of_immune <= time.time() - 1800:
                self.immune = False
                self.time_of_immune = None

        if self.cannot_attack == True:
            # Measures in seconds
            if self.cannot_attack_time <= time.time() - 1800:
                self.cannot_attack = False
                self.cannot_attack_time = None

        if self.defensive_maneuver == True:
            if self.defensive_maneuver_time <= time.time() - 1800:
                self.defnesive_maneuver = False
                self.defensive_maneuver_time = None
                self.defense_bonus -= 2

        if self.cast_defensive_maneuver == True:
            if self.defensive_maneuver_cast_time != datetime.datetime.now().date():
                self.cast_defensive_maneuver = False
                self.defensive_maneuver_cast_time = False

class Rogue(Player):
    def __init__(self):
        Player.__init__(self)
        self.sneak = False
        self.sneak_time = None
        self.sneak_cast = False
        self.sneak_cast_time = None

    def backstab(self, player2):
        x = player2.defense_bonus
        player2.defense_bonus = 0
        combat(self, player2)
        player2.defense_bonus = x

    def sneak(self):
        if self.sneak_cast == False:
            self.sneak = True
            self.sneak_time = time.time()
            self.sneak_cast = True
            self.sneak_cast_time = datetime.datetime.now().date()
        else:
            print("You cannot cast that again for another day.")

    def check(self):
        if self.immune == True:
            # Measures in seconds
            if self.time_of_immune <= time.time() - 1800:
                self.immune = False
                self.time_of_immune = None

        if self.cannot_attack == True:
            # Measures in seconds
            if self.cannot_attack_time <= time.time() - 1800:
                self.cannot_attack = False
                self.cannot_attack_time = None

        if self.sneak == True:
            if self.sneak_time <= time.time() - 1800:
                self.sneak = False
                self.sneak_time = None

        if self.sneak_cast == True:
            if self.sneak_cast_time != datetime.datetime.now().date():
                self.sneak_cast = False
                self.sneak_cast_time = False

x = Warrior()
y = Wizard()
print(x.hp)
print(y.hp)
x.rend(y)
print(x.hp)
print(y.hp)
y.fireball(x)
print(x.hp)
print(y.hp)
y.freeze(x)
combat(y,x)
print(x.hp)
print(y.hp)


import numpy as np
import pandas as pd
from sklearn import neighbors, tree
from sklearn import cross_validation
from . import Preprocessing
# import Preprocessing as Preprocessing

def excKNN(k, train_data, train_labels, test_data, test_labels):
    errorCount = 0.0
    knnclf = neighbors.KNeighborsClassifier(k, weights='distance')
    knnclf.fit(train_data, train_labels)
    numTestVecs = test_data.shape[0]
    for i in range(numTestVecs):
        classifierResult = knnclf.predict(test_data[i,:].reshape(1,-1))
#         print("the classifier came back with: ", classifierResult ,", the real answer is: " , bank_test_labels_arr[i])
        if (classifierResult != test_labels[i]):
            errorCount += 1.0
    print("the total error rate is: %f",errorCount / float(numTestVecs))

def startClassifyKNN():
	dataSet = Preprocessing.getDataFromCSV()
	train_data, train_labels, train_ids, test_data, test_labels, test_ids = sep_train_test(dataSet)

	train_norm = Preprocessing.completePreprocessing(train_data,train_data)
	test_norm = Preprocessing.completePreprocessing(train_data, test_data)

	knnclf = neighbors.KNeighborsClassifier(5, weights='distance')
	knnclf.fit(train_norm, train_labels)
	trainScore = knnclf.score(train_norm, train_labels)
	testScore = knnclf.score(test_norm, test_labels)
	print(trainScore)
	print(testScore)

def startClassifyTree():
	dataSet = Preprocessing.getDataFromCSV()
	train_data, train_labels, train_ids, test_data, test_labels, test_ids = sep_train_test(dataSet)
	treeclf = tree.DecisionTreeClassifier(criterion='entropy')
	treeclf = treeclf.fit(np.array(train_data), np.array(train_labels))
	print(treeclf.score(train_data, train_labels))
	print(treeclf.score(test_data, test_labels))

def test(cv=30):
	dataSet = Preprocessing.getDataFromCSV()
	data_ = dataSet.iloc[:,1:-1]
	labels_ = dataSet.iloc[:,-1]
	ids_ = dataSet.iloc[:,0]

	data_norm = Preprocessing.completePreprocessing(data_,data_)

	knnclf = neighbors.KNeighborsClassifier(5, algorithm='brute')
	scores_KNN = cross_validation.cross_val_score(knnclf, data_norm, labels_, cv=cv)
	print("Overall Accuracy: %0.2f (+/- %0.2f)" % (scores_KNN.mean(), scores_KNN.std() * 2))

	treeclf = tree.DecisionTreeClassifier(criterion='entropy')
	scores_ = cross_validation.cross_val_score(treeclf, np.array(data_), np.array(labels_), cv=cv)
	print("Overall Accuracy: %0.2f (+/- %0.2f)" % (scores_.mean(), scores_.std() * 2))

def sep_train_test(dataSet, percent_test_cases=0.20):
	random_data_set = dataSet.reindex(np.random.permutation(dataSet.index))
	number_test_cases = int(random_data_set.shape[0]*percent_test_cases)

	test_data = random_data_set.iloc[:number_test_cases,1:-1]
	test_labels = random_data_set.iloc[:number_test_cases,-1]
	test_ids = random_data_set.iloc[:number_test_cases,0]

	train_data = random_data_set.iloc[number_test_cases:,1:-1]
	train_labels = random_data_set.iloc[number_test_cases:,-1]
	train_ids = random_data_set.iloc[number_test_cases:,0]

	return train_data, train_labels, train_ids, test_data, test_labels, test_ids

categories = ['blues','classical','country','hiphop','jazz','metal','pop','punk','reggae','rnb','rock']

def transform_labels_to_numbers(labels_):
	i=0
	categ = np.zeros(shape=labels_.shape)
	for cat in categories:
		catTrues = labels_ == cat
		categ[np.array(catTrues == True)] = i
		i+=1
	return categ

def classify_KNN(k, cv=30):
	dataSet = Preprocessing.getDataFromCSV()
	data_ = dataSet.iloc[:,1:-1]
	labels_ = dataSet.iloc[:,-1]
	ids_ = dataSet.iloc[:,0]
	print("ESTA ACA")
	data_norm = Preprocessing.completePreprocessing(data_,data_)
	print("AVA VA A EHECUTAR ",data_norm.shape)
	knnclf = neighbors.KNeighborsClassifier(k, algorithm='auto')
	scores_KNN = cross_validation.cross_val_score(knnclf, data_norm, labels_, cv=cv)
	return "%0.2f (+/- %0.2f)" % (scores_KNN.mean(), scores_KNN.std() * 2)

def classify_Tree(cv=30):
	dataSet = Preprocessing.getDataFromCSV()
	data_ = dataSet.iloc[:,1:-1]
	labels_ = dataSet.iloc[:,-1]
	ids_ = dataSet.iloc[:,0]
	treeclf = tree.DecisionTreeClassifier(criterion='entropy')
	scores_ = cross_validation.cross_val_score(treeclf, np.array(data_), np.array(labels_), cv=cv)
	return "%0.2f (+/- %0.2f)" % (scores_.mean(), scores_.std() * 2)

def classify_song_tree(song):
	dataSet = Preprocessing.getDataFromCSV()
	data_ = dataSet.iloc[:,1:-1]
	labels_ = dataSet.iloc[:,-1]
	ids_ = dataSet.iloc[:,0]
	treeclf = tree.DecisionTreeClassifier(criterion='entropy')
	treeclf.fit(data_,labels_)
	category = treeclf.predict(song)
	return category[0]

# classify_KNN(3)
# startClassifyKNN()
# startClassifyTree()
# test()
# print(classify_KNN(20))


import sys
input = sys.stdin.readline
from collections import deque

dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]

def nor_bfs(x, y):
    queue = deque()
    queue.append((x, y))
    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < n and 0 <= ny < n and nor_visited[nx][ny] == 0 and color[x][y] == color[nx][ny]:
                queue.append((nx, ny))
                nor_visited[nx][ny] = 1

def abnor_bfs(x, y):
    queue = deque()
    queue.append((x, y))
    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < n and 0 <= ny < n and abnor_visited[nx][ny] == 0 and abcolor[x][y] == abcolor[nx][ny]:
                queue.append((nx, ny))
                abnor_visited[nx][ny] = 1

n = int(input())

color = []
for _ in range(n):
    color.append(list(input().rstrip()))

abcolor = []
for i in range(n):
    tmp = ''.join(color[i])
    tmp2 = tmp.replace('R', 'G')
    abcolor.append(list(tmp2))

nor_visited = [[0] * n for _ in range(n)]
abnor_visited = [[0] * n for _ in range(n)]
nor = 0
abnor = 0
ans = []
for i in range(n):
    for j in range(n):
        if nor_visited[i][j] == 0:
            nor_bfs(i, j)
            nor += 1
ans.append(nor)
for i in range(n):
    for j in range(n):
        if abnor_visited[i][j] == 0:
            abnor_bfs(i, j)
            abnor += 1
ans.append(abnor)
print(*ans)


class Address:

	def __init__(self):
		self.Line = ''
		self.City = ''
		self.State = ''
		self.Zip = ''

	def __init__(self, line, city, state, zipcode):
		self.Line = line
		self.City = city
		self.State = state
		self.Zip = zipcode

	def serialize(self):
		return {
    			'line': str(self.Line),
    			'city': str(self.City),
    			'state': str(self.State),
    			'zip': str(self.Zip)
    			}


from django.urls import path
from .views import *

urlpatterns = [
    path('', qna_board, name="qna_board"),
    path('<str:id>', qna_detail, name="qna_detail"),
    path('qna_new/', qna_new, name="qna_new"),
    path('qna_create/', qna_create, name="qna_create"),
    path('qna_edit/<str:id>', qna_edit, name="qna_edit"),
    path('qna_update/<str:id>', qna_update, name="qna_update"),
    path('qna_delete/<str:id>', qna_delete, name="qna_delete"),
    path('comment_new/<str:post_id>', comment_new, name='comment_new'),
    path('update/comment_new/<str:comment_id>', comment_update, name='comment_update'),
    path('delete/comment_new/<str:comment_id>', comment_delete, name='comment_delete'),
]


"""Игра угадай число.
Оценка эффективности использования трёх подходов:
1. Случайное угадывание;
2. Угадывание с коррекцией;
3. Бинарный поиск.
"""

import numpy as np

def random_predict(number: int = 1) -> int:
    """Рандомно угадываем число

    Args:
        number (int, optional): Загаданное число. Defaults to 1.

    Returns:
        int: Число попыток
    """
    count = 0

    while True:
        count += 1
        predict_number = np.random.randint(1, 101)  # Предполагаемое число
        if number == predict_number:
            break  # Выход из цикла если угадали
    return count

def hot_cold_predict(number: int = 1) -> int:
    """ Угадываем число при помощи алгоритма Угадывания с коррекцией:

    Алгоритм угадывания:
        Называем любое целое число predict_number от 1 до 100;
        Если это число равно задуманному, то мы угадали!;
        Если нет, то называем любое следующее число, в зависимости от того,
        больше или меньше predict_number загаданоого числа
        и продолжаем алгоритм.
    Функция принимает загаданное число и возвращает число попыток.

    Args:
        number (int, optional): Загаданное число. Defaults to 1.

    Returns:
        int: Число попыток
    """
    # Количество попыток
    count = 0

    # Левая и правая границы поиска числа
    left_num, right_num = 1, 101

    while True:
        count+=1
        predict_number = np.random.randint(left_num, right_num)  # Предполагаемое число

        if predict_number > number:
            right_num = predict_number

        elif predict_number < number:
            left_num = predict_number + 1

        else:
           break # Конец игры выход из цикла
    return count

def optimal_predict(number: int = 1) -> int:
    """ Угадываем число при помощи алгоритма бинарного поиска:

    Алгоритм угадывания:
        Положим left_num = 1 и rightt_num = 100.
        Называем число, равное middle = (left_num + right_num) // 2 ;
        Если это число равно задуманному, то мы угадали!;
        Если это число меньше задуманного, то положим left_num = middle + 1
        и продолжим алгоритм;
        Если это число больше задуманного, то положим right_num = middle - 1
        и продолжим алгоритм.
    Функция принимает загаданное число и возвращает число попыток

    Args:
        number (int, optional): Загаданное число. Defaults to 1.

    Returns:
        int: Число попыток
    """
    # Количество попыток
    count = 0

    # Левая и правая границы поиска числа
    left_num, right_num = 1, 100

    while True:
        count+=1
        middle = (left_num + right_num) // 2

        if middle > number:
            right_num = middle - 1

        elif middle < number:
            left_num = middle + 1

        else:
           break # Конец игры выход из цикла
    return count

def score_game(function_predict) -> int:
    """Какое среднее количество попыток нужно алгоритму для угадывания числа
    за 1000 проходов.

    Args:
        function_predict ([type]): функция угадывания

    Returns:
        int: среднее количество попыток
    """
    count_ls = []
    #np.random.seed(1)  # Фиксируем сид для воспроизводимости
    random_array = np.random.randint(1, 101, size=(1000))  # Загадали список чисел

    for number in random_array:
        count_ls.append(function_predict(number))

    score = int(np.mean(count_ls))
    print(f"Ваш алгоритм угадывает число в среднем за: {score} попыток")
    return  score

if __name__ == "__main__":
    # RUN
    score_game(optimal_predict)
    score_game(hot_cold_predict)
    score_game(random_predict)


from data.data_manager import DataManager
import pandas as pd
from sqlalchemy import create_engine

# K线切分, 分为x,y; y= 1day reward 3day reward 5day reward;
# 特征抽取:
    #1、最简单对K线的Summery
# 计算不同特征的Reward, 存入数据库; feature, feature_type, stock_code,stock_name, trade_day, reward_1d,reward_3d,reward_5d,reward_10d
# 对所有特征进行统计分析得到解结论

dm = DataManager()
stock_basic = dm.get_stock_basic()

FE_TYPE_PCT_2 = "pct_2"
sql_engine = create_engine("mysql+mysqlconnector://root:k135792684@127.0.0.1:3306/quant?auth_plugin=mysql_native_password", echo=False)

def analysis():
    if_exists = "replace"
    for idx,itm in stock_basic.iterrows():
        if idx !=0:
            if_exists="append"
        print(idx,itm['ts_code'])
        res = analysis_stock(itm['ts_code'],start_date="20110201")
        res.to_sql(name="stock_analysis1", con=sql_engine, if_exists=if_exists)
        #df = dm.k_line_daily(code=itm['ts_code'])

#获取变化率
def change_rate(cur_price,pre_price,type="pct"):

    res = (cur_price/pre_price-1)*100
    if type == FE_TYPE_PCT_2:
        if res >=9.5:res = 9
        elif res>=5:res =5
        elif res>=3:res=3
        elif res>=1:res =1
        elif res>=0:res=0
        elif res>-1:res=-0
        elif res>-3:res=-1
        elif res>-5:res=-3
        elif res>-9.5:res=-5
        else: res=-9
    return round(res,2)

def fe_kline_base(open,close,high,low,pre_close):
    res = ''
    res += str(change_rate(open,pre_close,type=FE_TYPE_PCT_2))
    res += str(change_rate(close,pre_close,type=FE_TYPE_PCT_2))
    res += str(change_rate(high,pre_close,type=FE_TYPE_PCT_2))
    res += str(change_rate(low,pre_close,type=FE_TYPE_PCT_2))
    return res

def get_reward(df,close,cur_idx,reward_day):
    #row_size = df.shape[0]
    idx = cur_idx - reward_day #0是最近一天
    if idx<0:   #row_size-1:
        return 0
    else:
        #print(df.loc[idx])
        end_close = df.loc[idx]["close"]
        return change_rate(end_close,close)

def analysis_stock(code,start_date):
    df = dm.k_line_daily(code,start_date)
    #df = df.sort_values(by=["trade_date"],ascending=[True])
    res = pd.DataFrame()
    for idx, itm in df.iterrows():
        fe_kine_pct2 = fe_kline_base(itm["open"],itm["close"],itm["high"],itm["low"],itm["pre_close"])
        close =itm["close"]
        stock_code =itm["ts_code"]
        trade_date =itm["trade_date"]
        #print(idx)
        reward_1d = get_reward(df,close,idx,1)
        reward_3d = get_reward(df,close,idx,3)
        reward_5d = get_reward(df,close,idx,5)
        reward_10d = get_reward(df,close,idx,10)
        data={"stock_code":stock_code,"trade_date":trade_date,
                "feature":fe_kine_pct2,"feature_type":'pct_2',
                "reward_1d":reward_1d,"reward_3d":reward_3d,
                "reward_5d":reward_5d,"reward_10d":reward_10d}

        #feature, feature_type, stock_code,stock_name, trade_day, reward_1d,reward_3d,reward_5d,reward_10d
        #df1 = pd.DataFrame(data=[[itm["ts_code"],itm["trade_date"],fe_kine_pct2,'pct_2',reward_1d,reward_3d,reward_5d,reward_10d]],
        #                   columns=["stock_code","trade_date","feature","feature_type","reward_1d","reward_3d","reward_5d","reward_10d"],
        #                   index=[idx])
        res =res.append(data,ignore_index=True)
        #print(res)
        #print(idx,itm["trade_date"],fe_kine_pct2,reward_1d,reward_3d,reward_5d,reward_10d)
        #print(idx,itm["open"],itm["close"],itm["high"],itm["low"],itm["pre_close"])
        #print(changeprate(itm["open"],itm["pre_close"]),change_rate(itm["close"],itm["pre_close"]))

    return res

#analysis_stock("000565.SZ")

analysis()


import logging
import logging.config
from pathlib import Path

from utils import read_json

def setup_logging(
    save_dir,
    root_dir="./",
    filename=None,
    log_config="logger/logger_config.json",
    default_level=logging.INFO,
):
    """
    setup logging configuration
    """
    log_config = Path(root_dir) / log_config
    if log_config.is_file():
        config = read_json(log_config)
        # modify logging paths based on run config
        for handler_k, handler_v in config["handlers"].items():
            if "filename" in handler_v:
                if filename is None or handler_k != "info_file_handler":
                    handler_v["filename"] = str(save_dir / handler_v["filename"])
                else:
                    handler_v["filename"] = str(save_dir / filename)

        logging.config.dictConfig(config)
    else:
        print(
            "warning: logging configuration file is not found in {}.".format(log_config)
        )
        logging.basicConfig(level=default_level)

LOG_LEVELS = {
    0: logging.WARNING,
    1: logging.INFO,
    2: logging.DEBUG,
}

def get_logger(name, verbosity=2):
    assert (
        verbosity in LOG_LEVELS
    ), "verbosity option {verbosity} is invalid. \
         Valid options are {LOG_LEVELS.keys()}."
    logger = logging.getLogger(name)
    logger.setLevel(LOG_LEVELS[verbosity])
    return logger


from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext_lazy as _

from django.conf import settings

if "notification" in settings.INSTALLED_APPS:
    from notification import models as notification
else:
    notification = None

from newprojects.models import Project, ProjectMember
from newprojects.forms import ProjectForm, ProjectUpdateForm

TOPIC_COUNT_SQL = """
SELECT COUNT(*)
FROM topics_topic
WHERE
    topics_topic.object_id = newprojects_project.id AND
    topics_topic.content_type_id = %s
"""
MEMBER_COUNT_SQL = """
SELECT COUNT(*)
FROM newprojects_projectmember
WHERE newprojects_projectmember.project_id = newprojects_project.id
"""

@login_required
def create(request, form_class=ProjectForm, template_name="newprojects/create.html"):
    project_form = form_class(request.POST or None)

    if project_form.is_valid():
        project = project_form.save(commit=False)
        project.creator = request.user
        project.save()
        project_member = ProjectMember(project=project, user=request.user)
        project.members.add(project_member)
        project_member.save()
        if notification:
            # @@@ might be worth having a shortcut for sending to all users
            notification.send(User.objects.all(), "projects_new_project",
                {"project": project}, queue=True)
        return HttpResponseRedirect(project.get_absolute_url())

    return render_to_response(template_name, {
        "project_form": project_form,
    }, context_instance=RequestContext(request))

def projects(request, template_name="newprojects/projects.html"):

    projects = Project.objects.all()

    search_terms = request.GET.get('search', '')
    if search_terms:
        projects = (projects.filter(name__icontains=search_terms) |
            projects.filter(description__icontains=search_terms))

    content_type = ContentType.objects.get_for_model(Project)

    projects = projects.extra(select=SortedDict([
        ('member_count', MEMBER_COUNT_SQL),
        ('topic_count', TOPIC_COUNT_SQL),
    ]), select_params=(content_type.id,))

    return render_to_response(template_name, {
        'projects': projects,
        'search_terms': search_terms,
    }, context_instance=RequestContext(request))

def delete(request, group_slug=None, redirect_url=None):
    project = get_object_or_404(Project, slug=group_slug)
    if not redirect_url:
        redirect_url = reverse('project_list')

    # @@@ eventually, we'll remove restriction that project.creator can't leave project but we'll still require project.members.all().count() == 1
    if (request.user.is_authenticated() and request.method == "POST" and
            request.user == project.creator and project.members.all().count() == 1):
        project.delete()
        request.user.message_set.create(message=_("Project %(project_name)s deleted.") % {"project_name": project.name})
        # no notification required as the deleter must be the only member

    return HttpResponseRedirect(redirect_url)

@login_required
def your_projects(request, template_name="newprojects/your_projects.html"):
    return render_to_response(template_name, {
        "projects": Project.objects.filter(members=request.user).order_by("name"),
    }, context_instance=RequestContext(request))

def project(request, group_slug=None, form_class=ProjectUpdateForm,
        template_name="newprojects/project.html"):
    project = get_object_or_404(Project, slug=group_slug)

    project_form = form_class(request.POST or None, instance=project)

    if not request.user.is_authenticated():
        is_member = False
    else:
        is_member = project.user_is_member(request.user)

    action = request.POST.get('action')
    if action == 'update' and project_form.is_valid():
        project = project_form.save()
    elif action == 'join':
        # @@@ should move to a method on the Project model?
        if not is_member:
            project_member = ProjectMember(project=project, user=request.user)
            project.members.add(project_member)
            project_member.save()
            request.user.message_set.create(
                message=_("You have joined the project %(project_name)s") % {"project_name": project.name})
            if notification:
                notification.send([project.creator], "projects_created_new_member", {"user": request.user, "project": project})
                notification.send(project.member_users.all(), "projects_new_member", {"user": request.user, "project": project})
        else:
            request.user.message_set.create(
                message=_("You are already a member of project %(project_name)s") % {"project_name": project.name})
    elif action == 'leave':
        project.members.remove(request.user)
        request.user.message_set.create(message="You have left the project %(project_name)s" % {"project_name": project.name})
        if notification:
            pass # @@@ no notification on departure yet

    # TODO: Shouldn't have to do this in the view. Should write new "groupurl" templatetag :(
    new_topic_url = reverse('topic_list', kwargs=project.get_url_kwargs())

    return render_to_response(template_name, {
        "project_form": project_form,
        "project": project,
        "is_member": is_member,
        "new_topic_url": new_topic_url,
    }, context_instance=RequestContext(request))