# -*- coding: utf-8 -*-
"""
Created on Fri Mar 02 15:36:19 2018

@author: zrssch
"""
from __future__ import division
from __future__ import print_function

import os
import sys
import utils.data_utils as data_utils
from seq2seq import Encoder, Decoder, Seq2Seq
import torch
from torch import optim
from torch.autograd import Variable
from torch.nn.utils import clip_grad_norm
from torch.nn import functional as F
import random
import numpy as np
import math
import pickle

sys.path.append('../utils')

def read_data(config, source_path, target_path, max_size=None):
    data_set = []
    source_file = open(source_path, 'r')
    target_file = open(target_path, 'r')
    source, target = source_file.readline(), target_file.readline()
    counter = 0
    while source and target and (not max_size or counter < max_size):
        counter += 1
        if counter % 100000 == 0:
            print("  reading disc_data line %d" % counter)
            sys.stdout.flush()
        source_ids = [int(x) for x in source.strip().split()]
        target_ids = [int(x) for x in target.strip().split()]
        target_ids.append(data_utils.EOS_ID)
        if max(len(source_ids), len(target_ids)) < config.maxlen:
            data_set.append([source_ids, target_ids])
        source, target = source_file.readline(), target_file.readline()
    source_file.close()
    target_file.close()
    return data_set

def prepare_data(gen_config):
    if os.path.exists('vocab') and os.path.exists('rev_vocab') and os.path.exists('dev_set') and os.path.exists('train_set'):
        fr_vocab = open('vocab','rb')
        fr_rev_vocab = open('rev_vocab','rb')
        fr_dev_set = open('dev_set','rb')
        fr_train_set = open('train_set','rb')
        vocab = pickle.load(fr_vocab)
        rev_vocab = pickle.load(fr_rev_vocab)
        dev_set = pickle.load(fr_dev_set)
        train_set = pickle.load(fr_train_set)
        fr_vocab.close()
        fr_rev_vocab.close()
        fr_dev_set.close()
        fr_train_set.close()
    else:
        train_path = os.path.join(gen_config.train_dir, "chitchat.train")
        voc_file_path = [train_path+".answer", train_path+".query"]
        vocab_path = os.path.join(gen_config.train_dir, "vocab%d.all" % gen_config.vocab_size)
        data_utils.create_vocabulary(vocab_path, voc_file_path, gen_config.vocab_size)
        vocab, rev_vocab = data_utils.initialize_vocabulary(vocab_path)

        print("Preparing Chitchat gen_data in %s" % gen_config.train_dir)
        train_query, train_answer, dev_query, dev_answer = data_utils.prepare_chitchat_data(
            gen_config.train_dir, vocab, gen_config.vocab_size)

        # Read disc_data into buckets and compute their sizes.
        print ("Reading development and training gen_data (limit: %d)."
                   % gen_config.max_train_data_size)
        dev_set = read_data(gen_config, dev_query, dev_answer)
        train_set = read_data(gen_config, train_query, train_answer, gen_config.max_train_data_size)

        fw_vocab = open('vocab','wb')
        fw_rev_vocab = open('rev_vocab','wb')
        fw_dev_set = open('dev_set','wb')
        fw_train_set = open('train_set','wb')
        pickle.dump(vocab, fw_vocab)
        pickle.dump(rev_vocab, fw_rev_vocab)
        pickle.dump(dev_set, fw_dev_set)
        pickle.dump(train_set, fw_train_set)
        fw_vocab.close()
        fw_rev_vocab.close()
        fw_dev_set.close()
        fw_train_set.close()
    return vocab, rev_vocab, dev_set, train_set

def prepare_data_new(gen_config):
    if os.path.exists('vocab') and os.path.exists('rev_vocab') and os.path.exists('dev_set') and os.path.exists('train_set'):
        fr_vocab = open('vocab','rb')
        fr_rev_vocab = open('rev_vocab','rb')
        fr_dev_set = open('dev_set','rb')
        fr_train_set = open('train_set','rb')
        vocab = pickle.load(fr_vocab)
        rev_vocab = pickle.load(fr_rev_vocab)
        dev_set = pickle.load(fr_dev_set)
        train_set = pickle.load(fr_train_set)
        fr_vocab.close()
        fr_rev_vocab.close()
        fr_dev_set.close()
        fr_train_set.close()
    else:
        '''
        a pair: the vocabulary (a dictionary mapping string to integers), and
        the reversed vocabulary (a list, which reverses the vocabulary mapping).
        '''
        train_set = []
        dev_set = []
        train_path = os.path.join(gen_config.train_dir, "t_given_s_dialogue_length2_6.txt")
        vocab_path = os.path.join(gen_config.train_dir, "movie_25000")
        fr1 = open(train_path, 'r')
        fr2 = open(vocab_path, 'r')
        line = fr1.readline()
        counter = 0
        while line:
            counter += 1
            if counter % 100000 == 0:
                print("  reading disc_data line %d" % counter)
                sys.stdout.flush()
            source_target = line.strip().split('|')
            source = source_target[0]
            target = source_target[1]
            source_ids = [int(x) for x in source.strip().split()]
            target_ids = [int(x) for x in target.strip().split()]
            target_ids.append(data_utils.EOS_ID)
            if max(len(source_ids), len(target_ids)) < gen_config.maxlen:
                if counter%100==0:
                    dev_set.append([source_ids, target_ids])
                else:
                    train_set.append([source_ids, target_ids])
            line = fr1.readline()
        fr1.close()
        print('read over')

        rev_vocab = []
        rev_vocab.extend(data_utils._START_VOCAB)
        rev_vocab.extend(fr2.readlines())
        rev_vocab.extend(data_utils._END_VOCAB)
        fr2.close()
        rev_vocab = [i.strip() for i in rev_vocab]
        vocab = dict([(x, y) for (y, x) in enumerate(rev_vocab)])
        print('write pickle start')
        fw_vocab = open('vocab','wb')
        fw_rev_vocab = open('rev_vocab','wb')
        fw_dev_set = open('dev_set','wb')
        fw_train_set = open('train_set','wb')
        pickle.dump(vocab, fw_vocab)
        pickle.dump(rev_vocab, fw_rev_vocab)
        pickle.dump(dev_set, fw_dev_set)
        pickle.dump(train_set, fw_train_set)
        fw_vocab.close()
        fw_rev_vocab.close()
        fw_dev_set.close()
        fw_train_set.close()
        print('write pickle done')
    return vocab, rev_vocab, dev_set, train_set

def create_model(gen_config):
    encoder = Encoder(gen_config.vocab_size, gen_config.emb_dim, gen_config.hidden_size, n_layers=2, dropout=0.5)
    decoder = Decoder(gen_config.emb_dim, gen_config.hidden_size, gen_config.vocab_size, n_layers=1, dropout=0.5)
    seq2seq = Seq2Seq(encoder, decoder).cuda()
    optimizer = optim.Adam(seq2seq.parameters(), lr=gen_config.lr)
    return seq2seq, optimizer

def getbatch(dataset, batch_size, maxlen):
    '''
    input:
    datase: [[source,target]...]
    output:
    encoder_inputs: double list, padded input and reversee, (batch_size, maxlen)
    decoder_inputs: double list, padded output and add 'go' flag, (batch_size, maxlen), ('go' and 'end')
    source_inputs: double list, origin input,
    target_inputs: double list, origin output, ('end')
    '''
    encoder_inputs = []
    decoder_inputs = []
    source_inputs = []
    target_inputs = []
    for i in range(batch_size):
        temp = random.choice(dataset)
        source = temp[0]
        source_inputs.append(source)
        target = temp[1]
        target_inputs.append(target)
        encoder_pad = [data_utils.PAD_ID] * (maxlen - len(source))
        encoder_inputs.append(list(reversed(source + encoder_pad)))
        decoder_pad = [data_utils.PAD_ID] * (maxlen - len(target) - 1)
        decoder_inputs.append([data_utils.GO_ID] + target + decoder_pad)
    return encoder_inputs, decoder_inputs, source_inputs, target_inputs

def train_with_reward(gen_config, seq2seq, optim_seq2seq, reward, train_query_neg, train_answer_gen):
    seq2seq.train()
    reward = reward*(gen_config.maxlen-1)
    src = torch.from_numpy(np.array(train_query_neg).T)
    trg = torch.from_numpy(np.array(train_answer_gen).T)
    src = Variable(src).cuda()
    trg = Variable(trg).cuda()
    optim_seq2seq.zero_grad()
    output = seq2seq(src, trg)
    loss = F.cross_entropy(output[1:].view(-1, gen_config.vocab_size),
                               trg[1:].contiguous().view(-1),
                               ignore_index=data_utils.PAD_ID, reduce=False)
    print('train with reward loss is:', loss)
    # print('len reward:', len(reward))
    loss_reward = torch.dot(Variable(torch.Tensor(reward)).cuda(), loss)/len(reward)
    loss_reward.backward()
    clip_grad_norm(seq2seq.parameters(), gen_config.grad_clip)
    optim_seq2seq.step()
    return loss_reward.data[0]

def teacher_forcing(gen_config, seq2seq, optim_seq2seq, encoder_inputs, decoder_inputs):
    seq2seq.train()
    src = torch.from_numpy(np.array(encoder_inputs).T)
    trg = torch.from_numpy(np.array(decoder_inputs).T)
    src = Variable(src).cuda()
    trg = Variable(trg).cuda()
    optim_seq2seq.zero_grad()
    output = seq2seq(src, trg)
    loss = F.cross_entropy(output[1:].view(-1, gen_config.vocab_size),
                               trg[1:].contiguous().view(-1),
                               ignore_index=data_utils.PAD_ID)
    print('teacher forcing loss is: ', loss)
    loss.backward()
    clip_grad_norm(seq2seq.parameters(), gen_config.grad_clip)
    optim_seq2seq.step()
    return loss.data[0]

def train(gen_config):
    print("begin pretrain gen model ...")
    vocab, rev_vocab, dev_set, train_set = prepare_data_new(gen_config)
    #seqq2seq model
    seq2seq, optimizer = create_model(gen_config)
    seq2seq.train()
    pad = data_utils.PAD_ID
    total_loss = 0
    b = 0
    while True:
        encoder_inputs, decoder_inputs, source_inputs, target_inputs = getbatch(train_set, gen_config.batch_size, gen_config.maxlen)
        b += 1
        src = torch.from_numpy(np.array(encoder_inputs).T)
        trg = torch.from_numpy(np.array(decoder_inputs).T)
        src = Variable(src).cuda()
        trg = Variable(trg).cuda()
        # src, trg = src.cuda(), trg.cuda()
        optimizer.zero_grad()
        output = seq2seq(src, trg)
        loss = F.cross_entropy(output[1:].view(-1, gen_config.vocab_size),
                               trg[1:].contiguous().view(-1),
                               ignore_index=pad)
        loss.backward()
        clip_grad_norm(seq2seq.parameters(), gen_config.grad_clip)
        optimizer.step()

        total_loss += loss.data[0]
        print("single step loss", loss.data[0])
        if b % 100 == 0 and b != 0:
            total_loss = total_loss / 100
            print("[%d][loss:%5.2f][pp:%5.2f]" %
                  (b, total_loss, math.exp(total_loss)))
            total_loss = 0
        if b % 1000 == 0:
            seq2seq.eval()
            total_val_loss = 0
            for i in range(100):
                val_encoder_inputs, val_decoder_inputs, val_source_inputs, val_target_inputs = getbatch(train_set, gen_config.batch_size, gen_config.maxlen)
                val_src = torch.from_numpy(np.array(val_encoder_inputs).T)
                val_trg = torch.from_numpy(np.array(val_decoder_inputs).T)
                val_src = Variable(val_src).cuda()
                val_trg = Variable(val_trg).cuda()
                # val_src, val_trg = val_src.cuda(), val_trg.cuda()
                val_output = seq2seq(val_src, val_trg)
                val_loss = F.cross_entropy(val_output[1:].view(-1, gen_config.vocab_size),
                               val_trg[1:].contiguous().view(-1),
                               ignore_index=pad)
                total_val_loss += val_loss.data[0]
            total_val_loss = total_val_loss/100.0
            print("[%d][val_loss:%5.2f][pp:%5.2f]" %
                  (b//1000, total_val_loss, math.exp(total_val_loss)))
            seq2seq.train()
            torch.save(seq2seq, './pre_seq2seq.pth')
            print("save model at step %d"%b)

def test_decoder(gen_config):
    # vocab_path = os.path.join(gen_config.train_dir, "vocab%d.all" % gen_config.vocab_size)
    # vocab, rev_vocab = data_utils.initialize_vocabulary(vocab_path)
    fr_vocab = open('vocab','rb')
    fr_rev_vocab = open('rev_vocab','rb')
    vocab = pickle.load(fr_vocab)
    rev_vocab = pickle.load(fr_rev_vocab)
    fr_vocab.close()
    fr_rev_vocab.close()
    # seq2seq, optimizer = create_model(gen_config, vocab)
    seq2seq = torch.load('./pre_seq2seq.pth')
    sys.stdout.write("> ")
    sys.stdout.flush()
    sentence = sys.stdin.readline()
    while sentence:
        source = data_utils.sentence_to_token_ids(sentence, vocab) # list
        encoder_pad = [data_utils.PAD_ID] * (gen_config.maxlen - len(source))
        encoder_inputs = [list(reversed(source + encoder_pad))]
        src = torch.from_numpy(np.array(encoder_inputs).T)
        src = Variable(src).cuda()
        probs, result = seq2seq.decode(src) # maxlen*1*vocab, a list
        ans = []
        for idx in result:
            if idx == data_utils.EOS_ID:
                break
            if idx != data_utils.PAD_ID:
                ans.append(rev_vocab[idx])
        print(" ".join(ans))
        print("> ", end="")
        sys.stdout.flush()
        sentence = sys.stdin.readline()

def gen_disc_data(gen_config):
    print("start gen disc data ...")
    vocab, rev_vocab, dev_set, train_set = prepare_data(gen_config)
    disc_train_query = open("train.query", "w")
    disc_train_answer = open("train.answer", "w")
    disc_train_gen = open("train.gen", "w")
    seq2seq  = torch.load('./pre_seq2seq.pth')
    num_steps = 0
    while num_steps<10000:
        encoder_inputs, decoder_inputs, source_inputs, target_inputs = getbatch(train_set, gen_config.batch_size, gen_config.maxlen)
        src = torch.from_numpy(np.array(encoder_inputs).T)
        trg = torch.from_numpy(np.array(decoder_inputs).T)
        src = Variable(src).cuda()
        trg = Variable(trg).cuda()
        probs, result = seq2seq.gen_data(src, trg)
        result = [list(i) for i in result]
        result = np.array(result).T.tolist()
        resps = []
        for each in result:
            temp = []
            for idx in each:
                if idx == data_utils.EOS_ID:
                    break
                if idx != data_utils.PAD_ID:
                    temp.append(idx)
            resps.append(temp)
        for query, answer, resp in zip(source_inputs, target_inputs, resps):
            answer_str = " ".join([str(rev_vocab[an]) for an in answer][:-1])
            disc_train_answer.write(answer_str)
            disc_train_answer.write("\n")

            query_str = " ".join([str(rev_vocab[qu]) for qu in query])
            disc_train_query.write(query_str)
            disc_train_query.write("\n")

            resp_str = " ".join([str(rev_vocab[output]) for output in resp])

            disc_train_gen.write(resp_str)
            disc_train_gen.write("\n")
        num_steps += 1
        if num_steps%5==0:
            print("generate disc data at %d step"%num_steps)
    disc_train_gen.close()
    disc_train_query.close()
    disc_train_answer.close()
    print("end gen disc data.")


from random import *
import combat
from index import *

###"""Inventaire du Hero ne pas toucher
char = {
    'xp' : {
        "lvl": 1,
        "xp" : 0,
        "lvlnext": 25,
    },
    'hands' :{
        'hand1' : 'épée rouillé',
        'armor' : 'cape noir'
    },
    'gold' : {
        'Argent' : 10000,
    },
    'inv' : {
        'Potion de soin n1' : 2,
        'Potion de mana n1' : 1,
        },
    'equipement' : {
        'épée rouillé' : 0,
    },
    'armor' :{
        'cape noir' : 0,
    }
}
###"""Inventaire du Hero ne pas toucher"""

#vendeur :
vendeur1 ={
    'buy' : {
        'Potion de soin n1': [20, 1, 1],
        'Potion de mana n1': [10, 1, 2],
        'armure en cuir' : [1, 3],
    },
    'inv1' :{
        'Potion de soin n1': 1,
    },
    'inv2' :{
        'Potion de mana n1': 1,
    },
    'equipement' : {

    },
    'armor' :{
        'armure en cuir' : 1
    }

}
#mobs
fermier = {
    'nom' : "Fermier",
    'xp' : {
        "xp" : randint(10, 12),
    },
    'gold' : {
        'Argent' : randint(5, 7),
    },
    'inv': {
        "Oeil humain": randint(1,2),
        "Bouse de vache" : randint(2,4)
    }
}

chevalier = {
    'nom' : "Chevalier",
    'xp' : {
        "xp" : randint(25, 30),
    },
    'gold' : {
        'Argent' : randint(10, 13),
    },
    'inv': {
        "Armoirie de chevalier": randint(0,6)
    }
}

vendeur = {
    'nom' : "Vendeur",
    'xp' : {
        "xp" : randint(15, 20),
    },
    'gold' : {
        'Argent' : randint(50, 55),
    },
    'inv': {
        'Potion de soin n1': 1
    }
}

gobelin = {
    'nom' : "Gobelin",
    'xp' : {
        "xp" : randint(20, 25),
    },
    'gold' : {
        'Argent' : randint(5, 7),
    },
    'inv': {
        'slipe de gobelin': randint(1,2)
    }
}


import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from tf_sys_register import SubWindow

import tf_yolo
import tf_firebase

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Main Window')
        self.setGeometry(100, 100, 300, 200)
        layout = QVBoxLayout()
        layout.addStretch(1)

        label = QLabel("TAVER")
        label.setAlignment(Qt.AlignCenter)
        font = label.font()
        font.setPointSize(30)
        label.setFont(font)
        self.label = label

        code = QLabel("미지정")
        code.setAlignment(Qt.AlignCenter)
        font = code.font()
        font.setPointSize(10)
        code.setFont(font)
        self.code = code

        btn1 = QPushButton("등록")
        btn1.clicked.connect(self.onButtonClicked)

        btn2 = QPushButton("실행")
        btn2.clicked.connect(self.onButtonPlay)

        layout.addWidget(label)
        layout.addWidget(code)
        layout.addWidget(btn1)
        layout.addWidget(btn2)

        layout.addStretch(1)

        centralWidget = QWidget()
        centralWidget.setLayout(layout)
        self.setCentralWidget(centralWidget)

    def onButtonClicked(self):
        win = SubWindow()
        win.showModal()

        self.code.setText(win.result)

    def onButtonPlay(self):
        saturation = tf_yolo.load_yolo()
        try:
            tf_firebase.update_firebase(str(self.code.text()), saturation)
        except Exception as e:
            print(e)

    def show(self):
        super().show()


import numpy as np
import matplotlib.pyplot as plt
import nltk
import textrank

from random import shuffle
from postprocessing import Postprocess
from preprocessing import Preprocessing
from text_cnn import TextCNN
from extension import Extension
from plotting import Plotting

class Main(object):
    """
    Runs the main functions of the system in order,
    collecting the summary results.
    """

    def __init__(self):
        self.pre = None
        self.post = None

    def load_dataset(self, stem):
        # Loads and reads in data files

        print("initialising training models...")

        self.pre = Preprocessing(stem)
        self.post = Postprocess(self.pre)

        print("reading files...")

        self.pre.read_files()

        assert(self.pre is not None)
        assert(self.post is not None)

    def text_rank(self):
        test_entries = self.pre.test_entries
        textrank.TextRank.run(test_entries)

    def extension(self):
        test_entries = self.pre.test_entries
        Extension(test_entries)

    def control_case(self):
        test_entries = self.pre.test_entries

        def get_summary_sentences(word_count, list):

            count = word_count
            summary = ""
            for sent in list:
                if count < 0:
                    break
                else:
                    index = None
                    for i in range(len(sent)):
                        if sent[i].isalnum():
                            index = i
                            break
                    new_sent = sent[index:]
                    length = len(nltk.word_tokenize(new_sent))
                    summary += new_sent + " "
                    count -= length

            return summary

        for e in test_entries:
            sentences = e.sentences
            new_sentences = sentences[:]  # Copy sentences
            shuffle(new_sentences)
            summary = get_summary_sentences(100, new_sentences)
            assert(summary is not None)
            e.control_sum = summary

    @staticmethod
    def digit_count(entries):
        # Counts number of digits present in all entries

        cnn_dig_count = 0
        tr_dig_count = 0
        for entry in entries:
            cnn_dig_count += sum(c.isdigit() for c in entry.generated_sum)
            tr_dig_count += sum(c.isdigit() for c in entry.text_rank_sum)
        print("CNN dig count= ", cnn_dig_count)
        print("TextRank dig count= ", tr_dig_count)

    def main(self):
        # Runs all preprocessing and evaluations to collect results

        print("loading datasets...")
        self.load_dataset(stem=False)
        print("running control case model...")
        self.control_case()
        print("running TextRank model...")
        self.text_rank()
        print("running CNN model...")
        self.cnn(train=False)
        print("running extension")
        self.extension()

        print("calculating rouge scores...")

        self.post.calculate_rouge(0.5)
        self.digit_count(self.pre.test_entries)

        # Prints three example summaries
        for x in range(3):
            print("CNN summary: ", self.pre.test_entries[x].generated_sum)
            print("TextRank summary: ", self.pre.test_entries[x].text_rank_sum)
            print("Combined summary: ", self.pre.test_entries[x].combined_sum)
            print("Gold Standard summary: ", self.pre.test_entries[x].summary)
            print("Doc ID: ",self.pre.test_entries[x].doc_id)
            print()

        plotter = Plotting(self.pre.test_entries)
        plotter.plot()

    def cnn(self, train):
        # Trains or loads CNN depending on train = True/False

        if train:
            print("getting initial salience scores...")
            self.pre.get_salience_scores(load=True)

            train_data, train_labels, _ = self.pre.get_cnn_vectors(train)

            assert(train_data is not None and train_labels is not None)

            # We've now pre process the documents, so now we can feed into the CNN

            TextCNN(train_data=train_data, train_labels=train_labels, num_filters=400, kernel_size=3)
            exit()
        else:
            _, _, test_data = self.pre.get_cnn_vectors(train)

            print("generating salience results...")

            gen_salience_results = TextCNN.eval(test_data)
            print(gen_salience_results)

            print("post-processing results...")
            self.post.get_results(gen_salience_results)

            print("getting summaries...")

            self.post.get_summary_sentences(100)
            self.post.return_summaries()

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


import pandas
from Gameplay import *
from Team import *
from DirectoryWide import *
import numpy
from alive_progress import alive_bar, alive_it
#"""
schedLength = input('How many games per season would you like? (20, 52, 162, Alt)')  # 1 and '' is 52, 2 is 162
if schedLength == '':
    schedLength = '52'
if schedLength == 'Alt':
    playoffSize = 'it literally doesnt matter'
else:
    playoffSize = input('What playoff format would you like? (8, 10, 12, DE)')  # 0 is 8, 1 is 10, 2 and '' is 12 (also 'DE12' for the fun one I'm gonna make)
#schedLength = '162'
#playoffSize = 'DE'

seriesHome = [None, [0], [0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0, 0]]
# First index is series length (in wins needed), second index: 0 means better seed hosts game, 1 means worse seed

print('Building the teams...')
NLEt = [Team('Washington Nationals ', 'WSN'), Team('New York Mets        ', 'NYM'),
        Team('Atlanta Braves       ', 'ATL'), Team('Miami Marlins        ', 'MIA'),
        Team('Philadelphia Phillies', 'PHI')]  # Teams
NLCt = [Team('Chicago Cubs         ', 'CHC'), Team('Cincinnati Reds      ', 'CIN'),
        Team('St. Louis Cardinals  ', 'STL'), Team('Pittsburgh Pirates   ', 'PIT'),
        Team('Milwaukee Brewers    ', 'MIL')]
NLWt = [Team('Los Angeles Dodgers  ', 'LAD'), Team('Arizona Diamondbacks ', 'ARI'),
        Team('San Fransisco Giants ', 'SFG'), Team('San Diego Padres     ', 'SDP'),
        Team('Colorado Rockies     ', 'COL')]
ALEt = [Team('New York Yankees     ', 'NYY'), Team('Tampa Bay Rays       ', 'TBR'),
        Team('Boston Red Sox       ', 'BOS'), Team('Toronto Blue Jays    ', 'TOR'),
        Team('Baltimore Orioles    ', 'BAL')]
ALCt = [Team('Minnesota Twins      ', 'MIN'), Team('Cleveland Guardians  ', 'CLE'),
        Team('Chicago White Sox    ', 'CHW'), Team('Kansas City Royals   ', 'KCR'),
        Team('Detroit Tigers       ', 'DET')]
ALWt = [Team('Houston Astros       ', 'HOU'), Team('Oakland Athletics    ', 'OAK'),
        Team('LA Angels of Anaheim ', 'LAA'), Team('Texas Rangers        ', 'TEX'),
        Team('Seattle Mariners     ', 'SEA')]
NLEs = pandas.DataFrame(numpy.array(NLEt), columns=['Team'])  # Standings
NLCs = pandas.DataFrame(numpy.array(NLCt), columns=['Team'])
NLWs = pandas.DataFrame(numpy.array(NLWt), columns=['Team'])
ALEs = pandas.DataFrame(numpy.array(ALEt), columns=['Team'])
ALCs = pandas.DataFrame(numpy.array(ALCt), columns=['Team'])
ALWs = pandas.DataFrame(numpy.array(ALWt), columns=['Team'])
Divisions = [NLEt, NLCt, NLWt, ALEt, ALCt, ALWt]
Standings = [NLEs, NLCs, NLWs, ALEs, ALCs, ALWs]
NLt = NLEt+NLCt+NLWt
ALt = ALEt+ALCt+ALWt
NLs = pandas.concat([NLEs, NLCs, NLWs])
ALs = pandas.concat([ALEs, ALCs, ALWs])
Leagues = [NLt, ALt]
MLBt = NLt + ALt
# INTER LEAGUE
geoRivals = [(NLEt[0], ALEt[4]), (NLEt[1], ALEt[0]), (NLEt[2], ALEt[3]), (NLEt[3], ALEt[1]), (NLEt[4], ALEt[2]),
             (NLCt[0], ALCt[2]), (NLCt[1], ALCt[1]), (NLCt[2], ALCt[3]), (NLCt[3], ALCt[4]), (NLCt[4], ALCt[0]),
             (NLWt[0], ALWt[2]), (NLWt[1], ALWt[3]), (NLWt[2], ALWt[1]), (NLWt[3], ALWt[4]), (NLWt[4], ALWt[0])]
# ^ These are the real geographic rivals
geoRivals2 = [(j[1], j[0]) for j in geoRivals]  # Home/Away Flip
interleagueSlates = [None]*14
NLHomes = random.sample(list(range(14)), k=7)
for i in range(14):
    interleagueSlates[i] = [(geoRivals[0][0], geoRivals[(i + 1) % 15][1]),
                            (geoRivals[1][0], geoRivals[(i + 2) % 15][1]),
                            (geoRivals[2][0], geoRivals[(i + 3) % 15][1]),
                            (geoRivals[3][0], geoRivals[(i + 4) % 15][1]),
                            (geoRivals[4][0], geoRivals[(i + 5) % 15][1]),
                            (geoRivals[5][0], geoRivals[(i + 6) % 15][1]),
                            (geoRivals[6][0], geoRivals[(i + 7) % 15][1]),
                            (geoRivals[7][0], geoRivals[(i + 8) % 15][1]),
                            (geoRivals[8][0], geoRivals[(i + 9) % 15][1]),
                            (geoRivals[9][0], geoRivals[(i + 10) % 15][1]),
                            (geoRivals[10][0], geoRivals[(i + 11) % 15][1]),
                            (geoRivals[11][0], geoRivals[(i + 12) % 15][1]),
                            (geoRivals[12][0], geoRivals[(i + 13) % 15][1]),
                            (geoRivals[13][0], geoRivals[(i + 14) % 15][1]),
                            (geoRivals[14][0], geoRivals[i % 15][1])]
    if i not in NLHomes:
        interleagueSlates[i] = [(j[1], j[0]) for j in interleagueSlates[i]]  # Flip home and away for half the slates
geoRivalsFinal = [geoRivals]  # Later we will be adding Lists of slates, so even though it's just 1 slate still need it.
geoRivals2Final = [geoRivals2]

def roundRobin(groups):
    for q in range(1):  # This is a slightly edited of a round robin algorithm i found online and stole
        schedule = []
        for div in groups:
            w = div.copy()
            random.shuffle(w)
            if len(w) % 2 == 1:
                w.append(None)
            n = len(w)
            d = list(range(n))
            mid = n // 2
            for i in range(n - 1):
                l1 = d[:mid]
                l2 = d[mid:]
                l2.reverse()
                round = []
                for j in range(mid):
                    t1 = w[l1[j]]
                    t2 = w[l2[j]]
                    if j == 0 and i % 2 == 1:
                        round.append((t2, t1))
                    else:
                        round.append((t1, t2))
                schedule.append(round)
                # rotate list by n/2, leaving last element at the end
                d = d[mid:-1] + d[:mid] + d[-1:]
        return schedule

for i in Divisions:
    random.shuffle(i)
# DIVISIONAL
bigSched = roundRobin(Divisions)
divisionalSlates = [None]*5
for i in range(5):
    divisionalSlates[i] = bigSched[i]+bigSched[i+5]+bigSched[i+10]+bigSched[i+15]+bigSched[i+20]+bigSched[i+25]
divisionalSlates2 = [[(j[1], j[0]) for j in i] for i in divisionalSlates]

# SAME LEAGUE
biggerSched = roundRobin(Leagues)
leagueSlates = [None]*15
for i in range(15):
    leagueSlates[i] = biggerSched[i] + biggerSched[i+15]
leagueSlates2 = [[(j[1], j[0]) for j in i] for i in leagueSlates]

# 52 Game Schedule - 15 Interleague + 1 extra georival, 16 Division, 20 non-div same league
schedule52 = geoRivalsFinal + geoRivals2Final + interleagueSlates + divisionalSlates + divisionalSlates2 + leagueSlates + leagueSlates2
random.shuffle(schedule52)

# 162 Game Schedule - 52 from there^ + 2 bonus division games, all played as 3 game series
miniSlates = [[(k[0], k[1]) for k in Divisions] + [(k[2], k[3]) for k in Divisions],
              [(k[1], k[2]) for k in Divisions] + [(k[3], k[4]) for k in Divisions],
              [(k[4], k[0]) for k in Divisions]]

base = schedule52 + miniSlates
random.shuffle(base)
schedule162 = [None]*177
for i in range(177):
    schedule162[i] = base[i//3]

# 20 Game Schedule - 2 Geo Rival + 8 divisional + 10 non divisional same league, Home = Away not promised
schedule20 = geoRivalsFinal + geoRivals2Final + divisionalSlates + leagueSlates
random.shuffle(schedule20)

schedule0 = []
#"""

def series(top, bot, l, pri=1, losers=False, wins=False):  # Top seed, bottom seed, games needed to win, print value
    top.usageReset()
    bot.usageReset()
    if wins:
        if bot.wins > top.wins:  # We are going to flip em
            hold = bot
            bot = top
            top = hold
    print(top.seed, top, top.record(), 'vs.', bot.seed, bot, bot.record(), 'best of', (l*2) - 1)
    top.pWins = 0
    bot.pWins = 0
    gameNum = 0
    while top.pWins < l and bot.pWins < l:
        if seriesHome[l][gameNum] == 0:
            game(top, bot, playoff=True, p=pri)
        else:
            game(bot, top, playoff=True, p=pri)
        print(top.ABR, top.pWins, bot.pWins, bot.ABR)
        gameNum += 1
    if not losers:
        if top.pWins == l:
            return top
        elif bot.pWins == l:
            return bot
    else:
        if top.pWins == l:
            return [top, bot]
        elif bot.pWins == l:
            return [bot, top]

def playIt(schedule):  # Plays the regular season
    for i in range(len(schedule)):
        if i == (len(schedule)//6)*3:
            print('HALFWAY STANDINGS')
            for k in Standings:
                k['Played'] = [j.played for j in k['Team']]
                k['Wins'] = [j.wins for j in k['Team']]
                k['Losses'] = k['Played'] - k['Wins']
                k['WPCT'] = (1000 * k['Wins']) // k['Played']
                k['Run D'] = [(j.runsFor - j.runsAgainst) for j in k['Team']]
                k.sort_values(['WPCT', 'Run D'], inplace=True, ascending=False)  # irl tiebreak is H2H
                k.reset_index(drop=True, inplace=True)
                print(k)
            print('ALL-STAR BREAK')
            WSHost = allstarGame(int(schedLength)//2)  # Winner of the ASG gets top seed in WS
            for dkajfhdkfh in NLt+ALt:  # i got annoyed
                dkajfhdkfh.setTeam(p=False)
        print('SLATE', i+1)
        slateScores = []
        for j in schedule[i]:
            if j[0] and j[1]:
                slateScores.append(game(j[0], j[1], p=0))
        print(slateScores)
    endOfYear(int(schedLength))  # Stats Leaders
    print('DIVISION STANDINGS')
    for i in Standings:
        i['Played'] = [j.played for j in i['Team']]
        i['Wins'] = [j.wins for j in i['Team']]
        i['Losses'] = i['Played'] - i['Wins']
        i['WPCT'] = (1000 * i['Wins']) // i['Played']
        i['Run D'] = [(j.runsFor - j.runsAgainst) for j in i['Team']]
        i.sort_values(['Wins', 'Run D'], inplace=True, ascending=False)
        i.iloc[0]['Team'].winDivision = True  # Secures playoff spot
        i.reset_index(drop=True, inplace=True)
        print(i)
    print('LEAGUE STANDINGS')
    for i in [NLs, ALs]:
        i['Played'] = [j.played for j in i['Team']]
        i['Wins'] = [j.wins for j in i['Team']]
        i['Losses'] = i['Played'] - i['Wins']
        i['WPCT'] = (1000 * i['Wins']) // i['Played']
        i['Run D'] = [(j.runsFor - j.runsAgainst) for j in i['Team']]
        i['D. Winner'] = [j.winDivision for j in i['Team']]
        i.sort_values(['D. Winner', 'WPCT', 'Run D'], inplace=True, ascending=False)
        i.reset_index(drop=True, inplace=True)
    print(NLs)
    print(ALs)
    if playoffSize in ['1', '8']:
        playoffs8(NLs, ALs, WSHost)
    elif playoffSize in ['2', '10']:
        playoffs10(NLs, ALs, WSHost)
    elif playoffSize in ['DE', 'DE12']:
        playoffsDP12(NLs, ALs)
    elif playoffSize == '0':
        pass
    else:
        playoffs12(NLs, ALs, WSHost)

def playoffs12(NLs, ALs, WSHost):  # New MLB playoff format, starting 2022
    NLdw = NLs.loc[NLs['D. Winner'] == True]
    ALdw = ALs.loc[ALs['D. Winner'] == True]
    NLwc = NLs.loc[NLs['D. Winner'] == False]
    ALwc = ALs.loc[ALs['D. Winner'] == False]
    NLplay = [NLdw.iloc[0]['Team'], NLdw.iloc[1]['Team'], NLdw.iloc[2]['Team'],
           NLwc.iloc[0]['Team'], NLwc.iloc[1]['Team'], NLwc.iloc[2]['Team']]
    ALplay = [ALdw.iloc[0]['Team'], ALdw.iloc[1]['Team'], ALdw.iloc[2]['Team'],
           ALwc.iloc[0]['Team'], ALwc.iloc[1]['Team'], ALwc.iloc[2]['Team']]
    for i in NLplay:
        i.seed = 'N'+str(NLplay.index(i) + 1)
    for i in ALplay:
        i.seed = 'A'+str(ALplay.index(i) + 1)
    print('NL Playoffs')
    bracket(NLplay)  # Prints a cute lil bracket to look at
    print('AL Playoffs')
    bracket(ALplay)
    print('National League Wild Card')
    NLWC1 = series(NLplay[3], NLplay[4], 2)
    NLWC2 = series(NLplay[2], NLplay[5], 2)
    print('American League Wild Card')
    ALWC1 = series(ALplay[3], ALplay[4], 2)
    ALWC2 = series(ALplay[2], ALplay[5], 2)
    print('National League Division Series')
    NLDS1 = series(NLplay[0], NLWC1, 3)
    NLDS2 = series(NLplay[1], NLWC2, 3)
    print('American League Division Series')
    ALDS1 = series(ALplay[0], ALWC1, 3)
    ALDS2 = series(ALplay[1], ALWC2, 3)
    print('National League Championship Series')
    if NLplay.index(NLDS1) < NLplay.index(NLDS2):
        NLCS = series(NLDS1, NLDS2, 4)
    else:
        NLCS = series(NLDS2, NLDS1, 4)
    print('American League Championship Series')
    if ALplay.index(ALDS1) < ALplay.index(ALDS2):
        ALCS = series(ALDS1, ALDS2, 4)
    else:
        ALCS = series(ALDS2, ALDS1, 4)
    print('World Series')
    if WSHost == 'NL':
        WS = series(NLCS, ALCS, 4)
    else:
        WS = series(ALCS, NLCS, 4)
    print(WS, 'wins the world series!!!')

def playoffs10(NLs, ALs, WSHost):  # MLB playoff 2012-2021 except Covid 2020
    NLdw = NLs.loc[NLs['D. Winner'] == True]
    ALdw = ALs.loc[ALs['D. Winner'] == True]
    NLwc = NLs.loc[NLs['D. Winner'] == False]
    ALwc = ALs.loc[ALs['D. Winner'] == False]
    NLplay = [NLdw.iloc[0]['Team'], NLdw.iloc[1]['Team'], NLdw.iloc[2]['Team'],
           NLwc.iloc[0]['Team'], NLwc.iloc[1]['Team']]
    ALplay = [ALdw.iloc[0]['Team'], ALdw.iloc[1]['Team'], ALdw.iloc[2]['Team'],
           ALwc.iloc[0]['Team'], ALwc.iloc[1]['Team']]
    for i in NLplay:
        i.seed = 'N'+str(NLplay.index(i) + 1)
    for i in ALplay:
        i.seed = 'A'+str(ALplay.index(i) + 1)
    print('NL Playoffs')
    bracket(NLplay)
    print('AL Playoffs')
    bracket(ALplay)
    print('National League Wild Card')
    NLWC = series(NLplay[3], NLplay[4], 1)
    print('American League Wild Card')
    ALWC = series(ALplay[3], ALplay[4], 1)
    print('National League Division Series')
    NLDS1 = series(NLplay[0], NLWC, 3)
    NLDS2 = series(NLplay[1], NLplay[2], 3)
    print('American League Division Series')
    ALDS1 = series(ALplay[0], ALWC, 3)
    ALDS2 = series(ALplay[1], ALplay[2], 3)
    print('National League Championship Series')
    if NLplay.index(NLDS1) < NLplay.index(NLDS2):
        NLCS = series(NLDS1, NLDS2, 4)
    else:
        NLCS = series(NLDS2, NLDS1, 4)
    print('American League Championship Series')
    if ALplay.index(ALDS1) < ALplay.index(ALDS2):
        ALCS = series(ALDS1, ALDS2, 4)
    else:
        ALCS = series(ALDS2, ALDS1, 4)
    print('World Series')
    if WSHost == 'NL':
        WS = series(NLCS, ALCS, 4)
    else:
        WS = series(ALCS, NLCS, 4)
    print(WS, 'wins the world series!!!')

def playoffs8(NLs, ALs, WSHost):  # MLB 1994-2011
    NLdw = NLs.loc[NLs['D. Winner'] == True]
    ALdw = ALs.loc[ALs['D. Winner'] == True]
    NLwc = NLs.loc[NLs['D. Winner'] == False]
    ALwc = ALs.loc[ALs['D. Winner'] == False]
    NLplay = [NLdw.iloc[0]['Team'], NLdw.iloc[1]['Team'], NLdw.iloc[2]['Team'],
           NLwc.iloc[0]['Team']]
    ALplay = [ALdw.iloc[0]['Team'], ALdw.iloc[1]['Team'], ALdw.iloc[2]['Team'],
           ALwc.iloc[0]['Team']]
    for i in NLplay:
        i.seed = 'N'+str(NLplay.index(i) + 1)
    for i in ALplay:
        i.seed = 'A'+str(ALplay.index(i) + 1)
    print('NL Playoffs')
    bracket(NLplay)
    print('AL Playoffs')
    bracket(ALplay)
    print('National League Division Series')
    NLDS1 = series(NLplay[0], NLplay[3], 3)
    NLDS2 = series(NLplay[1], NLplay[2], 3)
    print('American League Division Series')
    ALDS1 = series(ALplay[0], ALplay[3], 3)
    ALDS2 = series(ALplay[1], ALplay[2], 3)
    print('National League Championship Series')
    if NLplay.index(NLDS1) < NLplay.index(NLDS2):
        NLCS = series(NLDS1, NLDS2, 4)
    else:
        NLCS = series(NLDS2, NLDS1, 4)
    print('American League Championship Series')
    if ALplay.index(ALDS1) < ALplay.index(ALDS2):
        ALCS = series(ALDS1, ALDS2, 4)
    else:
        ALCS = series(ALDS2, ALDS1, 4)
    print('World Series')
    if WSHost == 'NL':
        WS = series(NLCS, ALCS, 4)
    else:
        WS = series(ALCS, NLCS, 4)
    print(WS, 'wins the world series!!!')

def playoffsDP12(NLs, ALs):  # No one ever has thought this was a good idea
    NLdw = NLs.loc[NLs['D. Winner'] == True]
    ALdw = ALs.loc[ALs['D. Winner'] == True]
    NLwc = NLs.loc[NLs['D. Winner'] == False]
    ALwc = ALs.loc[ALs['D. Winner'] == False]
    NLplay = [NLdw.iloc[0]['Team'], NLdw.iloc[1]['Team'], NLdw.iloc[2]['Team'],
              NLwc.iloc[0]['Team'], NLwc.iloc[1]['Team'], NLwc.iloc[2]['Team']]
    ALplay = [ALdw.iloc[0]['Team'], ALdw.iloc[1]['Team'], ALdw.iloc[2]['Team'],
              ALwc.iloc[0]['Team'], ALwc.iloc[1]['Team'], ALwc.iloc[2]['Team']]
    for i in NLplay:
        i.seed = 'N'+str(NLplay.index(i) + 1)
    for i in ALplay:
        i.seed = 'A'+str(ALplay.index(i) + 1)
    bracket(NLplay+ALplay)
    print('WINNERS QF')
    G1 = series(NLplay[0], ALplay[3], 3, losers=True)
    G2 = series(ALplay[1], NLplay[2], 3, losers=True)
    G3 = series(ALplay[0], NLplay[3], 3, losers=True)
    G4 = series(NLplay[1], ALplay[2], 3, losers=True)
    print('LOSERS R1')
    G5 = series(G1[1], NLplay[4], 2, losers=True)
    G6 = series(G2[1], ALplay[5], 2, losers=True)
    G7 = series(G3[1], ALplay[4], 2, losers=True)
    G8 = series(G4[1], NLplay[5], 2, losers=True)
    print('WINNERS SF')
    G9 = series(G1[0], G2[0], 3, losers=True, wins=True)
    G10 = series(G3[0], G4[0], 3, losers=True, wins=True)
    print('LOSERS R2')
    G11 = series(G5[0], G6[0], 2, losers=True, wins=True)
    G12 = series(G7[0], G8[0], 2, losers=True, wins=True)
    print('LOSERS R3')
    G13 = series(G10[1], G11[0], 3, losers=True)
    G14 = series(G9[1], G12[0], 3, losers=True)
    print('WINNERS FINAL')
    G15 = series(G9[0], G10[0], 4, losers=True, wins=True)
    print('LOSERS SF')
    G16 = series(G13[0], G14[0], 3, losers=True, wins=True)
    print('LOSERS FINAL')
    G17 = series(G15[1], G16[0], 4, losers=True)
    print('WORLD SERIES')
    G18 = series(G15[0], G17[0], 4)
    if G18 == G15[0]:
        G19 = G18
    else:
        G19 = series(G17[0], G15[0], 4)  # Losers winner gets home field in the bracket reset I think is fair
    print(G19, 'WINS THE WORLD SERIES')

def hrDerby(NLcontestants, ALcontestants, host):
    print('National League Contestants')
    for i in NLcontestants:
        print(i.bigLine())
    print('American League Contestants')
    for i in ALcontestants:
        print(i.bigLine())
    board = Scoreboard(host.ABR, 1)
    print('National League SF')
    NL1 = hrdMatchup(NLcontestants[0], NLcontestants[3], board)
    NL2 = hrdMatchup(NLcontestants[1], NLcontestants[2], board)
    print('American League SF')
    AL1 = hrdMatchup(ALcontestants[0], ALcontestants[3], board)
    AL2 = hrdMatchup(ALcontestants[1], ALcontestants[2], board)
    print('National League Final')
    NLwinner = hrdMatchup(NL1, NL2, board)
    print('American League Final')
    ALwinner = hrdMatchup(AL1, AL2, board)
    print('Grand Final')
    winner = hrdMatchup(NLwinner, ALwinner, board)
    print(winner.team, winner.idLine(), 'WINS THE TITLE')

def hrdMatchup(x, y, board):
    print(x.team, x.idLine(), 'v', y.team, y.idLine())
    xScore = 0
    xOuts = 0
    yScore = 0
    yOuts = 0
    swings = 0
    while xOuts < 10:
        res = hrdPitch(x, board)
        if res == True:
            xScore += 1
        elif res == '':
            pass
        else:
            xOuts += 1
        swings += 1
        if board.p >= 2:
            print(xScore, xOuts)
    while yOuts < 10:
        res = hrdPitch(y, board)
        if res == True:
            yScore += 1
        elif res == '':
            pass
        else:
            yOuts += 1
        if board.p >= 2:
            print(yScore, yOuts)
    if xScore > yScore:
        print(x.team, x.idLine(), 'Wins!', str(xScore)+'-'+str(yScore))
        return x
    elif yScore > xScore:
        print(y.team, y.idLine(), 'Wins!', str(yScore)+'-'+str(xScore))
        return y
    else:
        swings = 0
        while swings < 3 or xScore == yScore:
            if hrdPitch(x, board) == True:
                xScore += 1
            if hrdPitch(y, board) == True:
                yScore += 1
            swings += 1
            if board.p >= 2:
                print(x, xScore, y, yScore)
        if xScore > yScore:
            print(x.team, x.idLine(), 'Wins!', str(xScore)+'-'+str(yScore), 'after', swings, 'extra swings')
            return x
        elif yScore > xScore:
            print(y.team, y.idLine(), 'Wins!', str(yScore)+'-'+str(xScore), 'after', swings, 'extra swings')
            return y

def allstarGame(gp):  # I thought it would be fun
    AShost = random.choice(MLBt)
    print('ALL-STAR WEEKEND HOSTED BY', AShost)
    (NLh, NLp, ALh, ALp) = buildPDFs()
    # Set up the stats
    NLp['IP'] = [i.IP for i in list(NLp['Name'])]
    NLp['ERA'] = [i.ERA for i in list(NLp['Name'])]
    ALp['IP'] = [i.IP for i in list(ALp['Name'])]
    ALp['ERA'] = [i.ERA for i in list(ALp['Name'])]
    NLh['PA'] = [i.PA for i in list(NLh['Name'])]
    NLh['OPS'] = [i.OPS for i in list(NLh['Name'])]
    NLh['HR'] = [i.HR for i in list(NLh['Name'])]
    ALh['PA'] = [i.PA for i in list(ALh['Name'])]
    ALh['OPS'] = [i.OPS for i in list(ALh['Name'])]
    ALh['HR'] = [i.HR for i in list(ALh['Name'])]
    # HR derby contestants
    NLh.sort_values(['HR', 'OPS'], inplace=True, ascending=False)
    ALh.sort_values(['HR', 'OPS'], inplace=True, ascending=False)
    nlHRD = NLh.iloc[0:4, 0]
    alHRD = ALh.iloc[0:4, 0]
    hrDerby(list(nlHRD), list(alHRD), AShost)
    # Now the real AS stuff
    NLh.sort_values(['OPS'], inplace=True, ascending=False)
    ALh.sort_values(['OPS'], inplace=True, ascending=False)
    NLp.sort_values(['ERA'], inplace=True, ascending=True)
    ALp.sort_values(['ERA'], inplace=True, ascending=True)
    # Set the lineups
    NLdefense = [None] * 10
    NLbatting = pandas.DataFrame(columns=['Name', 'Team', 'Position', 'Offense', 'OPS'])
    NLstarter = NLp[(NLp['IP'] > gp/2) & (NLp['Pos']=='SP')].iloc[0]['Name']
    NLbullpen = NLp[(NLp['IP'] > gp/2) & ~(NLp['Name']==NLstarter)].iloc[0:15]
    NLbullpen['Available'] = [True for i in range(len(NLbullpen))]
    NLdefense[1] = NLstarter
    for i in range(2, 10):
        cur = NLh[(NLh['Pos'] == posNotation[i]) & (NLh['PA'] >= 2*gp)].iloc[0]['Name']
        NLdefense[i] = cur
        NLbatting.loc[len(NLbatting)] = [cur, cur.team, posNotation[i], cur.offense, cur.OPS]
    NLdh = NLh[~(NLh['Name'].isin(NLdefense)) & (NLh['PA'] >= 2*gp)].iloc[0]['Name']
    NLdefense[0] = NLdh
    NLbatting.loc[len(NLbatting)] = [NLdh, NLdh.team, 'DH', NLdh.offense, NLdh.OPS]
    NLbatting.sort_values(['Offense', 'OPS'], ascending=False, inplace=True)
    NLAllStars = ASTeam('National League AS   ', 'NLA', NLdefense, NLbatting, NLbullpen)
    NLAllStars.lineupCard.closer = NLbullpen.iloc[0,0]
    NLAllStars.lineupCard.starters = pandas.concat([NLbatting, pandas.DataFrame([[NLstarter, NLstarter.team, 'SP',
        NLstarter.overall, NLstarter.ERA]], columns=['Name', 'Team', 'Position', 'Offense', 'OPS'])], ignore_index=True)
    # AL
    ALdefense = [None] * 10
    ALbatting = pandas.DataFrame(columns=['Name', 'Team', 'Position', 'Offense', 'OPS'])
    ALstarter = ALp[(ALp['IP'] > gp / 2) & (ALp['Pos'] == 'SP')].iloc[0]['Name']
    ALbullpen = ALp[(ALp['IP'] > gp / 2) & ~(ALp['Name'] == ALstarter)].iloc[0:15]
    ALbullpen['Available'] = [True for i in range(len(ALbullpen))]
    ALdefense[1] = ALstarter
    for i in range(2, 10):
        cur = ALh[(ALh['Pos'] == posNotation[i]) & (ALh['PA'] >= 2 * gp)].iloc[0]['Name']
        ALdefense[i] = cur
        ALbatting.loc[len(ALbatting)] = [cur, cur.team, posNotation[i], cur.offense, cur.OPS]
    ALdh = ALh[~(ALh['Name'].isin(ALdefense)) & (ALh['PA'] >= 2 * gp)].iloc[0]['Name']
    ALdefense[0] = ALdh
    ALbatting.loc[len(ALbatting)] = [ALdh, ALdh.team, 'DH', ALdh.offense, ALdh.OPS]
    ALbatting.sort_values(['Offense', 'OPS'], ascending=False, inplace=True)
    ALAllStars = ASTeam('American League AS   ', 'ALA', ALdefense, ALbatting, ALbullpen)
    ALAllStars.lineupCard.closer = ALbullpen.iloc[0, 0]
    ALAllStars.lineupCard.starters = pandas.concat([ALbatting, pandas.DataFrame([[ALstarter, ALstarter.team, 'SP',
        ALstarter.overall, ALstarter.ERA]],columns=['Name', 'Team', 'Position','Offense', 'OPS'])],ignore_index=True)
    # Play the game
    if AShost in NLt:
        ASTeams = [NLAllStars, ALAllStars]
        NLAllStars.hostABR = AShost.ABR
    else:
        ASTeams = [ALAllStars, NLAllStars]
        ALAllStars.hostABR = AShost.ABR
    for i in ASTeams:
        i.setTeam()
    game(ASTeams[0], ASTeams[1], p=2, stam=25)
    if NLAllStars.wins > 0:
        print('NATIONAL LEAGUE WINS')
        return 'NL'
    else:
        print('AMERICAN LEAGUE WINS')
        return 'AL'

def endOfYear(gp):
    (NLh, NLp, ALh, ALp) = buildPDFs()
    # pitchers
    NLp['IP'] = [i.IP for i in list(NLp['Name'])]
    NLp['ERA'] = [i.ERA for i in list(NLp['Name'])]
    NLp['W'] = [i.W for i in list(NLp['Name'])]
    NLp['S'] = [i.S for i in list(NLp['Name'])]
    NLp['K%'] = [i.Kp for i in list(NLp['Name'])]
    NLp['RA'] = [round(i.rAdded, 2) for i in list(NLp['Name'])]
    NLp['wRA'] = [i.wRA for i in list(NLp['Name'])]
    ALp['IP'] = [i.IP for i in list(ALp['Name'])]
    ALp['ERA'] = [i.ERA for i in list(ALp['Name'])]
    ALp['W'] = [i.W for i in list(ALp['Name'])]
    ALp['S'] = [i.S for i in list(ALp['Name'])]
    ALp['K%'] = [i.Kp for i in list(ALp['Name'])]
    ALp['RA'] = [round(i.rAdded, 2) for i in list(ALp['Name'])]
    ALp['wRA'] = [i.wRA for i in list(ALp['Name'])]
    # hitters
    NLh['PA'] = [i.PA for i in list(NLh['Name'])]
    NLh['HR'] = [i.HR for i in list(NLh['Name'])]
    NLh['OPS'] = [i.OPS for i in list(NLh['Name'])]
    NLh['SB'] = [i.SB for i in list(NLh['Name'])]
    NLh['SB%'] = [i.Sp for i in list(NLh['Name'])]
    NLh['RA'] = [round(i.rAdded, 2) for i in list(NLh['Name'])]
    NLh['wRC+'] = [i.wRCp for i in list(NLh['Name'])]
    ALh['PA'] = [i.PA for i in list(NLh['Name'])]
    ALh['HR'] = [i.HR for i in list(ALh['Name'])]
    ALh['OPS'] = [i.OPS for i in list(ALh['Name'])]
    ALh['SB'] = [i.SB for i in list(ALh['Name'])]
    ALh['SB%'] = [i.Sp for i in list(ALh['Name'])]
    ALh['RA'] = [round(i.rAdded, 2) for i in list(ALh['Name'])]
    ALh['wRC+'] = [i.wRCp for i in list(ALh['Name'])]
    print('End of year statistical leaders')
    print('Pitching-NL')
    NLp.sort_values(['IP'], inplace=True, ascending=False)
    print(NLp.head())
    NLp.sort_values(['ERA'], inplace=True, ascending=True)
    print(NLp[NLp['IP'] >= gp].head())
    NLp.sort_values(['W'], inplace=True, ascending=False)
    print(NLp.head())
    NLp.sort_values(['S'], inplace=True, ascending=False)
    print(NLp.head())
    NLp.sort_values(['K%'], inplace=True, ascending=False)
    print(NLp[NLp['IP'] >= gp].head())
    NLp.sort_values(['RA'], inplace=True, ascending=False)
    print(NLp.head())
    NLp.sort_values(['wRA'], inplace=True, ascending=True)
    print(NLp[NLp['IP'] >= gp].head())
    print('Pitching-AL')
    ALp.sort_values(['IP'], inplace=True, ascending=False)
    print(ALp.head())
    ALp.sort_values(['ERA'], inplace=True, ascending=True)
    print(ALp[ALp['IP'] >= gp].head())
    ALp.sort_values(['W'], inplace=True, ascending=False)
    print(ALp.head())
    ALp.sort_values(['S'], inplace=True, ascending=False)
    print(ALp.head())
    ALp.sort_values(['K%'], inplace=True, ascending=False)
    print(ALp[ALp['IP'] >= gp].head())
    ALp.sort_values(['RA'], inplace=True, ascending=False)
    print(ALp.head())
    ALp.sort_values(['wRA'], inplace=True, ascending=True)
    print(ALp[ALp['IP'] >= gp].head())
    print('Hitting-NL')
    NLh.sort_values(['OPS'], inplace=True, ascending=False)
    print(NLh[NLh['PA'] >= 3*gp].head())
    NLh.sort_values(['HR'], inplace=True, ascending=False)
    print(NLh.head())
    NLh.sort_values(['SB'], inplace=True, ascending=False)
    print(NLh.head())
    NLh.sort_values(['RA'], inplace=True, ascending=False)
    print(NLh.head())
    NLh.sort_values(['wRC+'], inplace=True, ascending=False)
    print(NLh[NLh['PA'] >= 3*gp].head())
    print('Hitting-AL')
    ALh.sort_values(['OPS'], inplace=True, ascending=False)
    print(ALh[ALh['PA'] >= 3*gp].head())
    ALh.sort_values(['HR'], inplace=True, ascending=False)
    print(ALh.head())
    ALh.sort_values(['SB'], inplace=True, ascending=False)
    print(ALh.head())
    ALh.sort_values(['RA'], inplace=True, ascending=False)
    print(ALh.head())
    ALh.sort_values(['wRC+'], inplace=True, ascending=False)
    print(ALh[ALh['PA'] >= 3*gp].head())
    for i in MLBt:
        if i.controlled:
            print('Your Team')
            for j in i.hitters['Name']:
                print(j.bigLine())
            for j in i.rotation['Name']:
                print(j.bigLine())
            for j in i.bullpen['Name']:
                print(j.bigLine())
    if builder:
        gameplayEOY()

def bracket(teams):  # Derpy as hell but I like how it looks this way
    if len(teams) == 8:
        print(teams[0].ABR + '|')
        print('   |____')
        print(teams[7].ABR + '|    |')
        print('        |____')
        print(teams[3].ABR + '|    |    |')
        print('   |____|    |')
        print(teams[4].ABR + '|         |')
        print('             |___')
        print(teams[1].ABR + '|         |')
        print('   |____     |')
        print(teams[6].ABR + '|    |    |')
        print('        |____|')
        print(teams[2].ABR + '|    |')
        print('   |____|')
        print(teams[5].ABR + '|')
    elif len(teams) == 6:
        print('     ' + teams[0].ABR+'|')
        print('        |____')
        print(teams[3].ABR + '|    |    |')
        print('   |____|    |')
        print(teams[4].ABR + '|         |____')
        print('     ' + teams[1].ABR+'|    |')
        print('        |____|')
        print(teams[2].ABR + '|    |')
        print('   |____|')
        print(teams[5].ABR + '|')
    elif len(teams) == 5:
        print('     ' + teams[0].ABR + '|')
        print('        |____')
        print(teams[3].ABR + '|    |    |')
        print('   |____|    |')
        print(teams[4].ABR + '|         |____')
        print('     ' + teams[1].ABR + '|    |')
        print('        |____|')
        print('     '+teams[2].ABR+'|')
    elif len(teams) == 4:
        print(teams[0].ABR + '|')
        print('   |____')
        print(teams[3].ABR + '|    |')
        print('        |____')
        print(teams[2].ABR + '|    |')
        print('   |____|')
        print(teams[3].ABR + '|')
    elif len(teams) == 12:
        print('WINNERS BRACKET')
        print(teams[0].ABR + '|')
        print('   |____')
        print(teams[9].ABR + '|    |')
        print('        |____')
        print(teams[7].ABR + '|    |    |')
        print('   |____|    |')
        print(teams[2].ABR + '|         |')
        print('             |___')
        print(teams[6].ABR + '|         |')
        print('   |____     |')
        print(teams[3].ABR + '|    |    |')
        print('        |____|')
        print(teams[1].ABR + '|    |')
        print('   |____|')
        print(teams[8].ABR + '|')
        print('LOSERS BRACKET')
        print('___|')
        print('   |____')
        print(teams[4].ABR + '|')
        print()
        print('___|')
        print('   |____')
        print(teams[11].ABR + '|')
        print()
        print('___|')
        print('   |____')
        print(teams[10].ABR + '|')
        print()
        print('___|')
        print('   |____')
        print(teams[5].ABR + '|')

def offseason(year, p, holdovers):
    freeAgents = pandas.DataFrame(columns=['Name', 'Pos1', 'Pos2', 'Age', 'Core', 'OVR', 'Value'])
    pDeals = 0
    full = True if year <= simYears else False
    for i in NLt+ALt:
        teamFAs = i.reset()
        freeAgents = pandas.concat([freeAgents, teamFAs], ignore_index=True)
        i.prospectsAvailable(full)
        if not full and i.controlled:
            i.needCheck()
            print(*i.needs)
    if not full:
        prospectDraft(p)
    for i in MLBt:
        i.prospects.sort_values(['Value'], inplace=True, ascending=False, ignore_index=True)
    if faFormat == 1:  # EXCEL THING
        freeAgents = pandas.concat([freeAgents, holdovers])
        go = True
        roundNum = 0
        while go:
            if roundNum > 10:
                p = 2
            if p > 0:
                print('ROUND', roundNum+1)
            go = False
            for i in NLt+ALt:
                i.needCheck()
                if i.needs[0] > 0 or i.needs[2] > 0 or i.needs[3] > 0:
                    go = True
                    if p > 1:
                        print(i.ABR, *i.needs)
                    i.contractBundle(freeAgents, roundNum, year, p)
            if p > 0:
                print('Prospect Deals')
            for i in NLt + ALt:
                for j in i.prospects['Name']:
                    sign = j.acceptDeal()
                    if sign is not None:
                        pDeals += 1
                        if isinstance(j, Hitter) and p > 0:
                            print(j.pos + '/' + j.secondary, j.smallLine(), 'signs with', sign[0], 'for', sign[1], 'years',
                                  sign[2], 'AAV')
                        elif p > 0:
                            print(j.pos+'   ', j.smallLine(), 'signs with', sign[0], 'for', sign[1], 'years', sign[2], 'AAV')
                        i.prospects.drop(i.prospects[i.prospects['Name'] == j].index, inplace=True)
                        i.prospects.reset_index(drop=True, inplace=True)
            if p > 0:
                print('FA Deals')
            for i in freeAgents['Name']:
                sign = i.acceptDeal()
                if sign is not None:
                    if isinstance(i, Hitter) and p > 0:
                        print(i.idLine(), 'signs with', sign[0], 'for', sign[1], 'years', sign[2], 'AAV')
                    elif p > 0:
                        print(i.idLine(), 'signs with', sign[0], 'for', sign[1], 'years', sign[2], 'AAV')
                    freeAgents.drop(freeAgents[freeAgents['Name'] == i].index, inplace=True)
            roundNum += 1
        if p > 0:
            print('FREE AGENCY IS DONE AFTER', roundNum-1, 'ROUNDS')
    else:
        freeAgents.sort_values(['Core', 'OVR'], inplace=True, ignore_index=True, ascending=False)
        #with alive_bar(len(freeAgents), dual_line=True, title='FAs') as bar:
        if p == 0:
            for i in alive_it(range(len(freeAgents))):
                if auctionHelperThing(freeAgents, i, p, year):
                    break
        else:
            for i in range(len(freeAgents)):
                if auctionHelperThing(freeAgents, i, p, year):
                    break
        if p >= 1:
            print('FILL-IN')
        for j in MLBt:
            j.fillIn(p)
    for i in NLt+ALt:
        i.hitters.sort_values(['Overall', 'Offense'], inplace=True, ascending=False)
        i.rotation.sort_values(['Core', 'Extension'], inplace=True, ascending=False)
        i.bullpen.sort_values(['Core', 'Extension'], inplace=True, ascending=False)
        i.setTeam()
        i.lineupCard = Lineup(i.rotation, i.hitters, i.ABR)
        i.lineupCard.closer = i.bullpen.iloc[0, 0]
    if p > 0 and faFormat == 1:
        print(len(freeAgents[freeAgents['Age'] >= 8]), 'have retired')
        return freeAgents[freeAgents['Age'] < 8]
    elif p > 0:
        print(len(freeAgents), 'have retired')
        return None

def prospectDraft(p):
    draftOrder = pandas.DataFrame(columns=['Team', 'Previous Wins'])
    for i in MLBt:
        draftOrder.loc[len(draftOrder)] = [i, i.prevWins]
    draftOrder.sort_values(['Previous Wins'], inplace=True, ignore_index=True, ascending=True)
    print(draftOrder)
    prospects = pandas.DataFrame(columns=['Name', 'Pos1', 'Pos2', 'Age', 'Core', 'OVR', 'Value'])
    for i in range(30*draftDepth):
        inf = Hitter(nameGen(), random.choice(infieldPos), hand=random.choice(hitterHand), top=8)
        inf.age = 1
        inf.secondary = random.choice(infieldPos)
        prospects.loc[len(prospects)] = [inf, inf.pos, inf.secondary, 1, inf.offense, inf.overall, 0]
    for i in range(30*draftDepth):
        out = Hitter(nameGen(), random.choice(outfieldPos), hand=random.choice(hitterHand), top=8)
        out.age = 1
        out.secondary = random.choice(outfieldPos)
        prospects.loc[len(prospects)] = [out, out.pos, out.secondary, 1, out.offense, out.overall, 0]
    for i in range(30*min(draftDepth, 3)):
        sp = Pitcher(nameGen(), 'SP', hand=random.choice(pitcherHand), top=8)
        sp.age = 1
        prospects.loc[len(prospects)] = [sp, 'SP', numpy.nan, 1, sp.overall, sp.total, 0]
    for i in range(30*draftDepth):
        rp = Pitcher(nameGen(), 'RP', hand=random.choice(pitcherHand), top=8)
        rp.age = 1
        prospects.loc[len(prospects)] = [rp, 'RP', numpy.nan, 1, rp.overall, rp.total, 0]
    if p > 0:
        print('Welcome to the Prospect Draft!!')
    for i in range(min(4*draftDepth, 15)):
        print(f'ROUND {i+1}')
        for j in range(30):
            team = draftOrder.loc[j, 'Team']
            pick = team.prospectDrafter(prospects, )
            prospects.drop(prospects[prospects['Name'] == pick].index, inplace=True)
            if p > 0:
                print(f'Pick {i+1}.{j+1}: {team.ABR} selects {pick.idLine()}')

def auctionHelperThing(freeAgents, i, p, year):
    # if i%20 == 0:
    # print(str(i)+'/'+str(len(freeAgents)))
    if i > 125 and i % 5 == 0:
        if areWeDone():
            print('stopping early at', i)
            return True
    prospectsOffered = []
    player = freeAgents.loc[i, 'Name']
    if p >= 1:
        print('PLAYER IS:', player.idLine())
    for j in MLBt:
        if j.controlled:
            if i == 0:
                j.next = 0
            if j.next == i:
                offer = j.selfAuction(freeAgents, player, p, year)
            else:
                offer = None
            if j.next == i:
                j.next += 1
        else:
            offer = j.auction(player, p, year)
        if offer is not None:
            if offer != player:
                prospectsOffered.append(offer)
    for k in [player] + prospectsOffered:
        sign = k.acceptDeal()
        if sign is not None:
            if isinstance(k, Hitter) and p > 0:
                print(k.idLine(), 'signs with', sign[0], 'for', sign[1], 'years', sign[2], 'AAV')
            elif p > 0:
                print(k.idLine(), 'signs with', sign[0], 'for', sign[1], 'years', sign[2], 'AAV')
            if k == player:
                freeAgents.drop(freeAgents[freeAgents['Name'] == i].index, inplace=True)
            sign[0].needCheck()
            if p >= 2:
                print(sign[0], 'has remaining budget of', sign[0].budgetRemaining(year), round(sign[0].hitterCon, 1),
                      round(sign[0].spCon, 1), round(sign[0].rpCon, 1), *sign[0].needs)
    return False

def areWeDone():
    for i in MLBt:
        if len(i.hitters) < 13 or len(i.rotation) < 5 or len(i.bullpen) < 8:
            return False
    return True

def holdUpdate(holdovers):
    res = pandas.DataFrame(columns=['Name', 'Pos1', 'Pos2', 'Age', 'Core', 'OVR', 'Value'])
    if holdovers is not None:
        for i in holdovers['Name']:
            i.age += 1
            i.boost(ageCurve(i.age, i.controlled))
            if isinstance(i, Hitter):
                res.loc[len(res)] = [i, i.pos, i.secondary, i.age, i.offense, i.overall, 0]
            else:
                res.loc[len(res)] = [i, i.pos, i.secondary, i.age, i.overall, i.total, 0]
    return res

def buildPDFs():
    # Build DFs of all hitters and pitchers for each league for AS selection and EOY awards
    NLh = pandas.DataFrame(columns=['Name', 'Pos', 'OVR', 'Team'])  # NL Hitters
    NLp = pandas.DataFrame(columns=['Name', 'Pos', 'OVR', 'Team'])  # NL Pitchers
    ALh = pandas.DataFrame(columns=['Name', 'Pos', 'OVR', 'Team'])
    ALp = pandas.DataFrame(columns=['Name', 'Pos', 'OVR', 'Team'])
    for i in NLt:
        for j in i.hitters['Name']:
            j.team = i.ABR
            NLh.loc[len(NLh)] = [j, j.pos, j.offense, i.ABR]
    for i in NLt:
        for j in i.rotation['Name']:
            j.team = i.ABR
            NLp.loc[len(NLp)] = [j, 'SP', j.overall, i.ABR]
        for j in i.bullpen['Name']:
            j.team = i.ABR
            NLp.loc[len(NLp)] = [j, 'RP', j.overall, i.ABR]
    for i in ALt:
        for j in i.hitters['Name']:
            j.team = i.ABR
            ALh.loc[len(ALh)] = [j, j.pos, j.offense, i.ABR]
    for i in ALt:
        for j in i.rotation['Name']:
            j.team = i.ABR
            ALp.loc[len(ALp)] = [j, 'SP', j.overall, i.ABR]
        for j in i.bullpen['Name']:
            j.team = i.ABR
            ALp.loc[len(ALp)] = [j, 'RP', j.overall, i.ABR]
    return (NLh, NLp, ALh, ALp)

# Different League Format
def format2():
    random.shuffle(MLBt)
    for dkajfhdkfh in MLBt:  # i got annoyed
        dkajfhdkfh.setTeam()
    group1A = MLBt[0:5]
    group1B = MLBt[5:10]
    group1C = MLBt[10:15]
    group1D = MLBt[15:20]
    group1E = MLBt[20:25]
    group1F = MLBt[25:30]
    groups1 = [group1A, group1B, group1C, group1D, group1E, group1F]
    gNames = ['Group A', 'Group B', 'Group C', 'Group D', 'Group E', 'Group F']
    schedule = roundRobin(groups1)
    print('ROUND 1')
    R11 = [None] * 6
    R12 = [None] * 6
    R13 = [None] * 6
    R14 = [None] * 6
    R15 = [None] * 6
    for i in range(6):
        curStandings = pandas.DataFrame({'Team':groups1[i], 'Wins':[0]*5, 'RD':[0]*5})
        print(gNames[i])
        print(curStandings)
        curSched = schedule[i*5:i*5 + 5]
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[0], k[1], p=1)
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[1], k[0], p=1)
        curStandings['Wins'] = [z.wins for z in curStandings['Team']]
        curStandings['RD'] = [z.runsFor - z.runsAgainst for z in curStandings['Team']]
        curStandings.sort_values(['Wins', 'RD'], ascending=False, inplace=True, ignore_index=True)
        print(curStandings)
        R11[i] = curStandings.iloc[0].Team
        R12[i] = curStandings.iloc[1].Team
        R13[i] = curStandings.iloc[2].Team
        R14[i] = curStandings.iloc[3].Team
        R15[i] = curStandings.iloc[4].Team
    print('Advanced:', *R11)  # 6/6 advance from here
    print(*R12)  # 4/6 advance from here
    print(*R13)  # 3/6 advance from here
    print(*R14)  # 2/6 advance from here
    print('Eliminated:', *R15)  # 0/6 advance from here
    for i in MLBt:
        i.softReset()
    print('ROUND 2')
    groups2 = [R12, R13, R14]
    gNames2 = ['Second Place (4 Advance)', 'Third Place (3 Advance)', 'Fourth Place (2 Advance)']
    schedule2 = roundRobin(groups2)
    R2A = []
    R2E = []
    for i in range(3):
        curStandings = pandas.DataFrame({'Team':groups2[i], 'Wins':[0]*6, 'RD':[0]*6})
        print(gNames2[i])
        print(curStandings)
        curSched = schedule2[i*5:i*5 + 5]
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[0], k[1], p=1)
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[1], k[0], p=1)
        curStandings['Wins'] = [z.wins for z in curStandings['Team']]
        curStandings['RD'] = [z.runsFor - z.runsAgainst for z in curStandings['Team']]
        curStandings.sort_values(['Wins', 'RD'], ascending=False, inplace=True, ignore_index=True)
        print(curStandings)
        for j in range(6):
            if j < 4-i:
                R2A.append(curStandings.iloc[j].Team)
            else:
                R2E.append(curStandings.iloc[j].Team)
    print(*R2A)
    print('Eliminated:', *R2E)
    R3 = R2A + R11
    for i in R3:
        i.softReset()
    random.shuffle(R2A)
    group3A = R3[0:5]
    group3B = R3[5:10]
    group3C = R3[10:15]
    groups3 = [group3A, group3B, group3C]
    gNames3 = ['Group A', 'Group B', 'Group C']
    schedule3 = roundRobin(groups3)
    print('ROUND 3')
    R31 = [None] * 3
    R32 = [None] * 3
    R33 = [None] * 3
    R34 = [None] * 3
    R35 = [None] * 3
    for i in range(3):
        curStandings = pandas.DataFrame({'Team':groups3[i], 'Wins':[0]*5, 'RD':[0]*5})
        print(gNames3[i])
        print(curStandings)
        curSched = schedule3[i*5:i*5 + 5]
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[0], k[1], p=1)
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[1], k[0], p=1)
        curStandings['Wins'] = [z.wins for z in curStandings['Team']]
        curStandings['RD'] = [z.runsFor - z.runsAgainst for z in curStandings['Team']]
        curStandings.sort_values(['Wins', 'RD'], ascending=False, inplace=True, ignore_index=True)
        print(curStandings)
        R31[i] = curStandings.iloc[0].Team
        R32[i] = curStandings.iloc[1].Team
        R33[i] = curStandings.iloc[2].Team
        R34[i] = curStandings.iloc[3].Team
        R35[i] = curStandings.iloc[4].Team
    print('Advanced:', *R31)  # 3/3 advance from here
    print('Advanced:', *R32)  # 3/3 advance from here
    print(*R33)  # 1-2/3 advance from here
    print(*R34)  # 1-2/3 advance from here
    print('Eliminated:', *R35)  # 0/3 advance from here
    print('ROUND 4')
    group4 = R33 + R34
    for i in group4:
        i.softReset()
    R4A = []
    R4E = []
    schedule4 = roundRobin([group4])
    curStandings = pandas.DataFrame({'Team': group4, 'Wins': [0] * 6, 'RD': [0] * 6})
    print(curStandings)
    for j in schedule4:
        for k in j:
            if k[0] and k[1]:
                game(k[0], k[1], p=1)
    for j in schedule4:
        for k in j:
            if k[0] and k[1]:
                game(k[1], k[0], p=1)
    curStandings['Wins'] = [z.wins for z in curStandings['Team']]
    curStandings['RD'] = [z.runsFor - z.runsAgainst for z in curStandings['Team']]
    curStandings.sort_values(['Wins', 'RD'], ascending=False, inplace=True, ignore_index=True)
    print(curStandings)
    for i in range(6):
        if i < 2:
            R4A.append(curStandings.iloc[i].Team)
        else:
            R4E.append(curStandings.iloc[i].Team)
    print(*R4A)
    print('Eliminated:', *R4E)
    print('ROUND 5')
    R5 = R4A + R31 + R32
    for i in R5:
        i.softReset()
    random.shuffle(R5)
    group5A = R5[0:4]
    group5B = R5[4:8]
    groups5 = [group5A, group5B]
    gNames5 = ['Group A', 'Group B']
    schedule5 = roundRobin(groups5)
    R5A = []
    R5E = []
    for i in range(2):
        curStandings = pandas.DataFrame({'Team': groups5[i], 'Wins': [0] * 4, 'RD': [0] * 4})
        print(gNames5[i])
        print(curStandings)
        curSched = schedule5[i * 3:i * 3 + 3]
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[0], k[1], p=1)
        for j in curSched:
            for k in j:
                if k[0] and k[1]:
                    game(k[1], k[0], p=1)
        curStandings['Wins'] = [z.wins for z in curStandings['Team']]
        curStandings['RD'] = [z.runsFor - z.runsAgainst for z in curStandings['Team']]
        curStandings.sort_values(['Wins', 'RD'], ascending=False, inplace=True, ignore_index=True)
        print(curStandings)
        for j in range(4):
            if j == 0:
                R5A.append(curStandings.iloc[j].Team)
            else:
                R5E.append(curStandings.iloc[j].Team)
    print(*R5A)
    print('Eliminated:', *R5E)
    print('ROUND 6/WORLD SERIES')
    random.shuffle(R5A)
    WS = series(R5A[0], R5A[1], 4)
    print(WS, 'WINS THE WORLD SERIES!!!')
    endOfYear(15)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('scenic', '0059_census_dev'),
    ]

    operations = [
        migrations.RenameField(
            model_name='census',
            old_name='Dev',
            new_name='dev',
        ),
        migrations.AlterField(
            model_name='census',
            name='date',
            field=models.DateTimeField(auto_now=True, null=True),
        ),
    ]


# -*- coding: utf-8 -*-
"""
Created on Sat Nov 20 21:48:17 2021

@author: vonGostev
"""
import __init__
import numpy as np
import cupy as cp
import matplotlib.pyplot as plt
from lightprop2d import Beam2D, um, gaussian_beam
from scipy.sparse.linalg import expm
from scipy.sparse import csc_matrix

npoints = 256
cradius = 31.25
mod_radius = cradius / 2
area_size = cradius * 3.5
wl = 0.632
distances = [0, 100 * um, 1000 * um, 1]
bounds = [- area_size / 2, area_size / 2]
# loaded_data = np.load('smf_SI_3_properties.npz')
# loaded_data = np.load('mmf_SI_50_properties.npz')
loaded_data = np.load('mmf_GRIN_62.5_properties.npz')
modes = loaded_data['modes_list']
OP = csc_matrix(loaded_data['fiber_op'])
ibeam = Beam2D(
    area_size=area_size * um, npoints=npoints, wl=wl * um,
    init_field_gen=gaussian_beam,
    init_gen_args=(1, mod_radius * um,),
    use_gpu=True)
# init_field_gen=round_hole, init_gen_args=(cradius,))
profiles = [ibeam.iprofile]

mc = ibeam.deconstruct_by_modes(modes)
ibeam.construct_by_modes(modes, mc)
# ibeam.expand(ibeam.area_size * 2)

profiles.append(ibeam.iprofile)

mc = cp.array(expm(1j * OP * 10.).todense()) @ mc

for d in distances:
    ibeam.construct_by_modes(modes, mc)
    ibeam.propagate(d)
    profiles.append(ibeam.iprofile)
    ibeam.expand(ibeam.area_size * 2)
    ibeam.coarse(2)

fig, ax = plt.subplots(2, 3, figsize=(9, 6))
axes = ax.flatten()

i = 0
lbl = 'abcdef'
for ax, p in zip(axes, profiles):
    if i < 3:
        ax.imshow(p, extent=bounds*2)
    else:
        ax.imshow(p, extent=[- area_size / 2 * (i - 1),
                             area_size / 2 * (i - 1)]*2)
    ax.set_xlabel(f'({lbl[i]})')
    i += 1
plt.tight_layout()
plt.savefig('mmf/mmf_grin_gaussian_ip.png', dpi=100)
plt.show()

loaded_data.close()


__author__ = 'Zhiyang Ong'
__version__ = '0.1'
__date__ = 'February 25, 2025'

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

"""
	Import modules from The Python Standard Library.
	sys			Get access to any command-line arguments.
	os			Use any operating system dependent functionality.
	os.path		For pathname manipulations.

	subprocess -> call
				To make system calls.
	time		To measure elapsed time.
	warnings	Raise warnings.
	re			Use regular expressions.
	filecmp		For file comparison.
	datetime	For operations regarding date and time.
"""

import sys
import os
import os.path
from subprocess import call
import time
import warnings
import re
import filecmp
import datetime

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

#	Import Python Modules from installed Python packages, via PyPI

# Requires the following installation.
#pip install bibtexparser
# Import [Boulogne2022] [Boulogne2023a]
#import bibtexparser

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

#	Import Custom Python Modules

# Module to process input arguments to the script/program.
#from utilities.queue_ip_arguments import queue_ip_args
# Module to perform file I/O (input/output) operations.
#from utilities.file_io import file_io_operations

# Module for timing measurements.
from timing_measurements.performance_measurement_no_ns import execution_time_measurement_no_ns

###############################################################
# Main method for the program.

#	If this is executed as a Python script,
if __name__ == "__main__":
	#	= Set up loading of BibTeX database
	# Type of current time measurement.
	mode_current_time_measurement = "perf_counter"
	# Set the initial timestamp.
	execution_time_measurement_no_ns.set_initial_timestamp()
	"""
		Filename/path of the output file that contains the extracted BibTeX entries.
	"""
	output_filename = "./output-files/extracted_bibtext_entries.bib"
	# --------------------------------------------------------
	"""
		Check if the output filename is valid [DrakeJr2023a, from Generic Operating System Services: os — Miscellaneous operating system interfaces: Files and Directories].

		https://docs.python.org/3/library/os.html#os.access
		https://docs.python.org/3/library/os.html#os.W_OK
	"""
	if os.access(output_filename, os.W_OK):
		print("	Filename/Path to target output filename is valid:",output_filename,"=")
	else:
		print(">>>	Filename/Path to target output filename is invalid:",output_filename,"=")
		"""
			Get the absolute path containing the target output file.

			https://docs.python.org/3/library/os.path.html#os.path.abspath
		"""
		absolute_path_of_target_output_file = os.path.abspath(output_filename)
		print("	Path of target output:",absolute_path_of_target_output_file,"=")
		"""
			This approach only grabs the filename.
		path_of_directory_for_target_output_file = os.path.basename(output_filename)
		print("	Path of the directory for target output:",path_of_directory_for_target_output_file,"=")
		"""
		"""
			Get the path of the directory that would contain the target output file.

			https://docs.python.org/3/library/os.path.html#os.path.dirname
		"""
		path_of_directory_for_target_output_file = os.path.dirname(absolute_path_of_target_output_file)
		print("	Path of the directory for target output:",path_of_directory_for_target_output_file,"=")
		"""
			Is directory that would contain output file a valid directory?

			https://docs.python.org/3/library/os.path.html#os.path.isdir
		"""
		if os.path.isdir(path_of_directory_for_target_output_file):
			print("	Path of the directory for target output is valid.")
			print("	Target output file can be created.")
		else:
			print("	Path of the directory for target output is INVALID!!!")
			print("	Target output file cannot be created!!!")
			print("	Please kindly select path for output file in an existing directory!!!")
	output_filename = "./non-existent-directory/random_bibtex_database_non_existent.bib"
	if os.access(output_filename, os.W_OK):
		print("	Filename/Path to target output filename is valid:",output_filename,"=")
	else:
		print(">>>	Filename/Path to target output filename is invalid:",output_filename,"=")
		absolute_path_of_target_output_file = os.path.abspath(output_filename)
		print("	Path of target output:",absolute_path_of_target_output_file,"=")
		path_of_directory_for_target_output_file = os.path.dirname(absolute_path_of_target_output_file)
		print("	Path of the directory for target output:",path_of_directory_for_target_output_file,"=")
		if os.path.isdir(path_of_directory_for_target_output_file):
			print("	Path of the directory for target output is valid.")
			print("	Target output file can be created.")
		else:
			print("	Path of the directory for target output is INVALID!!!")
			print("	Target output file cannot be created!!!")
			print("	Please kindly select path for output file in an existing directory!!!")
	output_filename = "./output-files/z-empty-file.md"
	if os.access(output_filename, os.W_OK):
		print(">>>	Filename/Path to target output filename is valid:",output_filename,"=")
	else:
		print(">>>	Filename/Path to target output filename is invalid:",output_filename,"=")
	# --------------------------------------------------------
	# Get the elapsed time.
	elapsed_time = execution_time_measurement_no_ns.get_elapsed_time(mode_current_time_measurement)
	#temp_text = "Elapsed time:::"+str(datetime.timedelta(seconds=elapsed_time))+"=\n"
	print("Elapsed time:::",datetime.timedelta(seconds=elapsed_time),"=")


import socket

# the public network interface
HOST = "172.16.52.26"
PORT = 5025
# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(b'*iDN?')
print(s.recv(1024))


# https://www.codewars.com/kata/52774a314c2333f0a7000688

def valid_parentheses(string):
    count = 0
    for ch in string:
        if ch == '(':
            count += 1
        elif ch == ')':
            count -= 1
        if count < 0:
            return False
    return count == 0


import torch
import torch.nn as nn
import numpy as np
import pickle

iteration_num = 250
class MLPModel(nn.Module):
    # I defined the hyperparameters. These are in the parameters of the init function.
    def __init__(self,number_of_hidden_layers,number_of_neurons,learning_rate,activation_function,epoch):
        # I initialized the parameters.
        super(MLPModel,self).__init__()
        self.layer1 = None
        self.layer2 = None
        self.layer3 = None
        self.learning_rate = learning_rate
        self.number_of_hidden_layers = number_of_hidden_layers
        self.number_of_neurons = number_of_neurons
        self.activation_function = activation_function
        self.epoch = epoch
        self.hidden_layer_output = None
        self.hidden_layer_output_2 = None
        self.output_layer = None
        # Since there are two options of the hidden layer, we have to handle this situation in the two different block.
        if number_of_hidden_layers == 1:
            self.layer1 = nn.Linear(784,number_of_neurons)
            self.layer2 = nn.Linear(number_of_neurons,10)
        if number_of_hidden_layers == 2:
            self.layer1 = nn.Linear(784,number_of_neurons)
            self.layer2 = nn.Linear(number_of_neurons,number_of_neurons)
            self.layer3 = nn.Linear(number_of_neurons,10)

        # nn.LeakyReLU()
        # nn.PReLU()
        self.activation_function = activation_function()
        self.softmax_function = nn.Softmax(dim=1)

    def forward(self,x):
        # In forward propogation since there are two options in the hidden layer,
        # I divided into to two if part.
        if self.number_of_hidden_layers == 1:
            hidden_layer_output = self.activation_function(self.layer1(x))
            output_layer = self.layer2(hidden_layer_output)
        if self.number_of_hidden_layers == 2:
            hidden_layer_output = self.activation_function(self.layer1(x))
            hidden_layer_output_2 = self.activation_function(self.layer2(hidden_layer_output))
            output_layer = self.layer3(hidden_layer_output_2)
        return output_layer

# we load all the datasets of Part 3
x_train, y_train = pickle.load(open("data/mnist_train.data", "rb"))
x_validation, y_validation = pickle.load(open("data/mnist_validation.data", "rb"))
x_test, y_test = pickle.load(open("data/mnist_test.data", "rb"))

x_train = x_train/255.0
x_train = x_train.astype(np.float32)

x_test = x_test / 255.0
x_test = x_test.astype(np.float32)

x_validation = x_validation/255.0
x_validation = x_validation.astype(np.float32)

# and converting them into Pytorch tensors in order to be able to work with Pytorch
x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train).to(torch.long)

x_validation = torch.from_numpy(x_validation)
y_validation = torch.from_numpy(y_validation).to(torch.long)

x_test = torch.from_numpy(x_test)
y_test = torch.from_numpy(y_test).to(torch.long)

# In this part I created all the different model and then I created all different optimizer.
# Since I want to analyze all hyperparameter effect one by one, I changed the hyperparameter values one by one
# then I combined them.
model1 = MLPModel(1,8,0.001,nn.LeakyReLU,250)
optimizer1 = torch.optim.Adam(model1.parameters(),model1.learning_rate)
model2 = MLPModel(1,16,0.001,nn.LeakyReLU,250)
optimizer2 = torch.optim.Adam(model2.parameters(),model2.learning_rate)
model3 = MLPModel(1,8,0.002,nn.LeakyReLU,250)
optimizer3 = torch.optim.Adam(model3.parameters(),model3.learning_rate)
model4 = MLPModel(1,8,0.001,nn.PReLU,250)
optimizer4 = torch.optim.Adam(model4.parameters(),model4.learning_rate)
model5 = MLPModel(1,8,0.001,nn.LeakyReLU,500)
optimizer5 = torch.optim.Adam(model5.parameters(),model5.learning_rate)
model6 = MLPModel(2,8,0.001,nn.LeakyReLU,250)
optimizer6 = torch.optim.Adam(model6.parameters(),model6.learning_rate)
model7 = MLPModel(2,16,0.001,nn.LeakyReLU,250)
optimizer7 = torch.optim.Adam(model7.parameters(),model7.learning_rate)
model8 = MLPModel(2,16,0.002,nn.LeakyReLU,250)
optimizer8 = torch.optim.Adam(model8.parameters(),model8.learning_rate)
model9 = MLPModel(2,16,0.002,nn.PReLU,500)
optimizer9 = torch.optim.Adam(model9.parameters(),model9.learning_rate)
model10 = MLPModel(2,16,0.01,nn.PReLU,500)
optimizer10 = torch.optim.Adam(model10.parameters(),model10.learning_rate)

# In this following code part, I added the model and optimizer to the list.
keep_all_model_and_optimizer = []
keep_all_model_and_optimizer.append((model1,optimizer1))
keep_all_model_and_optimizer.append((model2,optimizer2))
keep_all_model_and_optimizer.append((model3,optimizer3))
keep_all_model_and_optimizer.append((model4,optimizer4))
keep_all_model_and_optimizer.append((model5,optimizer5))
keep_all_model_and_optimizer.append((model6,optimizer6))
keep_all_model_and_optimizer.append((model7,optimizer7))
keep_all_model_and_optimizer.append((model8,optimizer8))
keep_all_model_and_optimizer.append((model9,optimizer9))
keep_all_model_and_optimizer.append((model10,optimizer10))

#keep_all_mean_accuracy = []
loss_function = torch.nn.CrossEntropyLoss()
mean_iterations = []

# Based on the recitation slides, since I have a 10 model the first loop range in the(0,100)
for i in range(0,10):
    # According to the assignment.pdf, we have to run each model 10 times, so this for loop range in between (1,11)
    for j in range(1,11):
        list_validation_accuracy = []
        for iteration in range(1, keep_all_model_and_optimizer[i][0].epoch + 1):
            # I did the loss_value, prediction calculations and backpropagation in this part.
            keep_all_model_and_optimizer[i][1].zero_grad()
            predictions = keep_all_model_and_optimizer[i][0](x_train)
            loss_value = loss_function(predictions, y_train)
            loss_value.backward()
            keep_all_model_and_optimizer[i][1].step()

            with torch.no_grad():
                #I calculate the validation prediction, loss and accuracy in the following code piece.
                validation_predictions = keep_all_model_and_optimizer[i][0](x_validation)
                validation_loss = loss_function(validation_predictions, y_validation)
                validation_prediction_arr = torch.argmax(validation_predictions, dim=1)
                validation_accuracy = validation_prediction_arr[validation_prediction_arr == y_validation].size()[0] / \
                                      y_validation.size()[0] * 100
                list_validation_accuracy.append(validation_accuracy)
                #print("iteration: %d - Validation Loss: %f - Validation accuracy %f" % (iteration, validation_loss, validation_accuracy))
        mean_iterations.append(sum(list_validation_accuracy) / len(list_validation_accuracy))

each_model_accuracy_mean = []
count = 0
# In the following for loop, I calculate the overall mean of the each model
for i in range(1,101):
    count += mean_iterations[i-1]
    if i % 10 == 0:
        each_model_accuracy_mean.append(count/10)
        count = 0

each_model_standard_deviation = []
tmp_list = []
# In the following code piece, I calculate the each standard deviation of the each model
for i in range(1,101):
    tmp_list.append(mean_iterations[i-1])
    if i % 10 == 0:
        each_model_standard_deviation.append(np.std(tmp_list))
        tmp_list = []
# I calculate the all confidence interval of the all model.
each_model_confidence_interval = []
for i in range(0,10):
    conf_left = each_model_accuracy_mean[i] - 1.96 * each_model_standard_deviation[i] / 3.16227
    conf_right = each_model_accuracy_mean[i] + 1.96 * each_model_standard_deviation[i] / 3.16227
    each_model_confidence_interval.append((conf_left,conf_right))

max_index = 0
max_val = each_model_accuracy_mean[0]
# In the following for loop I calculate the maximum value and maximum index.
for i in range(1,10):
    if each_model_accuracy_mean[i] > max_val:
        max_val = each_model_accuracy_mean[i]
        max_index = i

# In order the create last dataset, I join the validation and train dataset.
x_new_dataset = torch.cat((x_validation,x_train),dim=0)
y_new_dataset = torch.cat((y_validation,y_train),dim=0)

# I do the same calculations above, actually the code block is the repetaiton of the above code block,just
# some parameters is changed.
test_means = []
for j in range(1, 11):
    list_test_accuracy = []
    for iteration in range(1, keep_all_model_and_optimizer[max_index][0].epoch + 1):
        keep_all_model_and_optimizer[max_index][1].zero_grad()
        predictions = keep_all_model_and_optimizer[max_index][0](x_new_dataset)
        loss_value = loss_function(predictions, y_new_dataset)
        loss_value.backward()
        keep_all_model_and_optimizer[max_index][1].step()

        with torch.no_grad():
            test_predictions = keep_all_model_and_optimizer[max_index][0](x_test)
            test_loss = loss_function(test_predictions, y_test)
            test_prediction_arr = torch.argmax(test_predictions, dim=1)
            test_accuracy = test_prediction_arr[test_prediction_arr == y_test].size()[0] / \
                                  y_test.size()[0] * 100
            list_test_accuracy.append(test_accuracy)
            #print("iteration: %d - Validation Loss: %f - Validation accuracy %f" % (iteration, test_loss, test_accuracy))
    test_means.append(sum(list_test_accuracy) / len(list_test_accuracy))

# calculate standard deviation for the last train
last_mean = 0
# I calculated the last train mean and also the standard deviation, confidence interval
for i in range(1,11):
    last_mean += test_means[i-1]
    if i % 10 == 0:
        last_mean = last_mean/10
last_standard_dev = np.std(test_means)
last_conf_left = last_mean - 1.96 * last_standard_dev / 3.16227
last_conf_right = last_mean + 1.96 * last_standard_dev / 3.16227

# In the following code session, I printed the all the accuracy_mean, standard deviation and the confidence interval
# in order to use the part3 report
for i in range(1,11):
    print("Model: %d - Mean Value: %f " % (i, each_model_accuracy_mean[i-1]))
for i in range(1,11):
    print("Model: %d - Standard Deviation: %f " % (i, each_model_standard_deviation[i-1]))
for i in range(1,11):
    print("Model: %d - confidence interval left: %f - confidence interval left: %f " % (i, each_model_confidence_interval[i - 1][0],each_model_confidence_interval[i - 1][1]))

# I also print the maximum mean, maximum value, and the last train mean, standard deviation, and the confidence interval
print("Max mean index",max_index+1)
print("Max mean value",max_val)

print("Last train mean: ",last_mean)
print("Last train standard deviation", last_standard_dev)
print("Last conf_left: ",last_conf_left)
print("Last conf_right: ",last_conf_right)


#编写程序，输入一个十进制整数n，再输入一个进制base，把n转换为base进制，用七段数码管显示结果。
#要求：
#（1）写一个整数n转换为任意进制（小于等于16）的函数： def convert(n,base) 其中n是十进制整数，base表示进制。如convert(2019,16)表示把十进制整数2019转换为16进制。
#（2）作图窗口设置为800*400，从左边开始显示。颜色、画笔大小可自由设定，不能用默认值。
#（3）用字母A,b,C,d,E,F...依次表示10，11，12...
#（4）可以使用教材P140例7.2的函数
import turtle
n=eval(input('请输入一个十进制整数:'))
base=eval(input('请输入进制:'))
def convert(n,base):
    a=n
    b=base
    c=['0','1','2','3','4','5','6','7','8','9','A','b','C','d','E','F']
    d=''
    while a>1:
        e=a%b
        d=c[e]+d
        a=a//b
    return d
def drawGap():
    turtle.penup()
    turtle.fd(5)
def drawline(draw):#绘制单条线
    drawGap()
    turtle.pendown() if draw else turtle.penup()#如果draw为True则画笔启动
    turtle.fd(100)
    drawGap()
    turtle.right(90)#向前移动40像素后，前进方向右转90度
def drawDigit(digit):#绘制单个数字，调用drawLine()函数
    drawline(True) if digit in ['2','3','4','5','6','8','9','A','b','d','E','F'] else drawline(False)
    drawline(True) if digit in ['0','1','3','4','5','6','7','8','9','A','b','d'] else drawline(False)
    drawline(True) if digit in ['0','2','3','5','6','8','9','b','C','d','E'] else drawline(False)
    drawline(True) if digit in ['0','2','6','8','A','b','C','d','E','F'] else drawline(False)
    turtle.left(90)#方向左转90度
    drawline(True) if digit in ['0','4','5','6','8','9','A','b','C','E','F'] else drawline(False)
    drawline(True) if digit in ['0','2','3','5','6','7','8','9','A','C','E','F'] else drawline(False)
    drawline(True) if digit in ['0','1','2','3','4','7','8','9','A','d',] else drawline(False)
    turtle.left(180)
    turtle.penup()
    turtle.fd(20)
def main():
    turtle.setup(800,400)
    turtle.penup()
    turtle.pensize(5)
    turtle.pencolor('#520793')
    turtle.seth(180)
    turtle.fd(395)
    turtle.seth(0)
    for i in q:
        drawDigit(i)
    turtle.hideturtle()
    turtle.done()
q=convert(n,base)
print(q)
main()


""" Created by Vladimir Gonchrov, 11.04.2018
    This file declares races and types classes """

from unit import Unit

class Gondor(Unit):
    """docstring for Gondor"""

    def __init__(self, **characteristics):
        self.magic_spell = characteristics['magic_spell']
        super().__init__(**characteristics)

class Izengard(Unit):
    """docstring for Izengard"""

    def __init__(self, **characteristics):
        self.fury = characteristics['fury']
        super().__init__(**characteristics)

class DamageDealer(Unit):
    """docstring for Damage_dealer"""

    def __init__(self, **characteristics):
        self.attack = characteristics['attack']
        self.attack_range = characteristics['attack_range']
        self.attack_type = characteristics['attack_type']
        super().__init__(**characteristics)

    def action(self, enemy, reply=True):
        if self.attack_type == 'phys':
            protection_factor = enemy.phys_resistance
        else:
            protection_factor = enemy.magic_resistance
        difference = self.attack - protection_factor - enemy.defence
        if difference > 0:
            enemy.health = max(enemy.health - difference, 0)
            if enemy.health > 0:
                if isinstance(enemy, DamageDealer) and enemy.attack_range >= \
                        self.attack_range and reply == True:
                    enemy.action(self, reply=False)

    def get_attack(self):
        return self.attack

class Support(Unit):
    """docstring for Support"""

    def __init__(self, **characteristics):
        self.heal = characteristics['heal']
        self.increase_attack = characteristics['increase_attack']
        self.increase_defence = characteristics['increase_defence']
        super().__init__(**characteristics)

    def action(self, ally):
        ally.defence += self.increase_defence
        ally.attack += self.increase_attack
        ally.heal += self.heal

    def get_attack(self):
        return 0


"""
file: tasks.py
author: Faisal Alzahrany
description: homework
"""

from dataclasses import *
from priority_queue import *

@dataclass
class Task:
    name: str
    priority: int

def make_task(name,priority):
    return Task(name,priority)

def test_tasks():
    q = make_priority_queue()
    enqueue(q, make_task("Task1", 5))
    enqueue(q, make_task("Task2", 7))
    enqueue(q,make_task("Task3",1))
    enqueue(q,make_task("Task4",9))
    t = front(q)
    print("Highest priority task is", t.name, "with priority",
          t.priority)
    t = back(q)
    print("Lowest priority task is", t.name, "with priority",
          t.priority)
    while not is_empty(q):
        t = front(q)
        dequeue(q)

def main():
    test_tasks()

main()


# -*- coding: utf-8 -*-
"""
data access

@author: hch
@date  : 2021/12/8
"""
from pymongo import MongoClient
import redis

from conf.config import APP_CONF

class MongoDao:
    def __init__(self):
        self.client = MongoClient(APP_CONF.mongodb.conn)
        self.db = self.client.get_database('wx_chat_bot')

    def log_msg(self, msg):
        self.db.get_collection('msg').insert_one({
            '_id': msg.msgId,
            'content': msg.content,
            'from_user_nick_name': msg.user.nickName,
            'from_user_name': msg.fromUserName,
            'to_user_name': msg.toUserName,
            'create_time': msg.createTime,
        })

class RedisDao:
    pool = redis.ConnectionPool(decode_responses=True)
    r = redis.Redis(connection_pool=pool, decode_responses=True)

if __name__ == '__main__':
    dao = MongoDao()
    print(dao.client.get_database('wx_chat_bot').get_collection('msg').find_one())