import requests
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Reads in the PPG for each team in 2022
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2022-04-05"

html = requests.get(url).content
ppg2022_list = pd.read_html(html)
ppg2022 = ppg2022_list[0]

# Reads in the Opposing team's PPG for each team in 2022
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2022-04-05"

html = requests.get(url).content
oppPpg2022_list = pd.read_html(html)
oppPpg2022 = oppPpg2022_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2022 = oppPpg2022.drop(oppPpg2022.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2022 = oppPpg2022.rename(columns={'2021': 'OppPPG'})

ppg2022 = ppg2022.drop(ppg2022.columns[[0,3,4,5,6,7]], axis=1)
ppg2022 = ppg2022.rename(columns={'2021': 'PPG'})

# Reads in the PPG for each team in 2021
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2021-04-06"

html = requests.get(url).content
ppg2021_list = pd.read_html(html)
ppg2021 = ppg2021_list[0]

# Reads in the Opposing team's PPG for each team in 2021
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2021-04-06"

html = requests.get(url).content
oppPpg2021_list = pd.read_html(html)
oppPpg2021 = oppPpg2021_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2021 = oppPpg2021.drop(oppPpg2021.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2021 = oppPpg2021.rename(columns={'2020': 'OppPPG'})

ppg2021 = ppg2021.drop(ppg2021.columns[[0,3,4,5,6,7]], axis=1)
ppg2021 = ppg2021.rename(columns={'2020': 'PPG'})

# Reads in the PPG for each team in 2019
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2019-04-09"

html = requests.get(url).content
ppg2019_list = pd.read_html(html)
ppg2019 = ppg2019_list[0]

# Reads in the Opposing team's PPG for each team in 2019
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2019-04-09"

html = requests.get(url).content
oppPpg2019_list = pd.read_html(html)
oppPpg2019 = oppPpg2019_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2019 = oppPpg2019.drop(oppPpg2019.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2019 = oppPpg2019.rename(columns={'2018': 'OppPPG'})

ppg2019 = ppg2019.drop(ppg2019.columns[[0,3,4,5,6,7]], axis=1)
ppg2019 = ppg2019.rename(columns={'2018': 'PPG'})

# Reads in the PPG for each team in 2018
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2018-04-03"

html = requests.get(url).content
ppg2018_list = pd.read_html(html)
ppg2018 = ppg2018_list[0]

# Reads in the Opposing team's PPG for each team in 2018
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2018-04-03"

html = requests.get(url).content
oppPpg2018_list = pd.read_html(html)
oppPpg2018 = oppPpg2018_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2018 = oppPpg2018.drop(oppPpg2018.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2018 = oppPpg2018.rename(columns={'2017': 'OppPPG'})

ppg2018 = ppg2018.drop(ppg2018.columns[[0,3,4,5,6,7]], axis=1)
ppg2018 = ppg2018.rename(columns={'2017': 'PPG'})

# Reads in the PPG for each team in 2017
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2017-04-04"

html = requests.get(url).content
ppg2017_list = pd.read_html(html)
ppg2017 = ppg2017_list[0]

# Reads in the Opposing team's PPG for each team in 2017
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2017-04-04"

html = requests.get(url).content
oppPpg2017_list = pd.read_html(html)
oppPpg2017 = oppPpg2017_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2017 = oppPpg2017.drop(oppPpg2017.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2017 = oppPpg2017.rename(columns={'2016': 'OppPPG'})

ppg2017 = ppg2017.drop(ppg2017.columns[[0,3,4,5,6,7]], axis=1)
ppg2017 = ppg2017.rename(columns={'2016': 'PPG'})

# Reads in the PPG for each team in 2016
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2016-04-05"

html = requests.get(url).content
ppg2016_list = pd.read_html(html)
ppg2016 = ppg2016_list[0]

# Reads in the Opposing team's PPG for each team in 2016
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2016-04-05"

html = requests.get(url).content
oppPpg2016_list = pd.read_html(html)
oppPpg2016 = oppPpg2016_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2016 = oppPpg2016.drop(oppPpg2016.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2016 = oppPpg2016.rename(columns={'2015': 'OppPPG'})

ppg2016 = ppg2016.drop(ppg2016.columns[[0,3,4,5,6,7]], axis=1)
ppg2016 = ppg2016.rename(columns={'2015': 'PPG'})

# Reads in the PPG for each team in 2015
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2015-04-06"

html = requests.get(url).content
ppg2015_list = pd.read_html(html)
ppg2015 = ppg2015_list[0]

# Reads in the Opposing team's PPG for each team in 2015
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2015-04-06"

html = requests.get(url).content
oppPpg2015_list = pd.read_html(html)
oppPpg2015 = oppPpg2015_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2015 = oppPpg2015.drop(oppPpg2015.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2015 = oppPpg2015.rename(columns={'2014': 'OppPPG'})

ppg2015 = ppg2015.drop(ppg2015.columns[[0,3,4,5,6,7]], axis=1)
ppg2015 = ppg2015.rename(columns={'2014': 'PPG'})

# Reads in the PPG for each team in 2014
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2014-04-07"

html = requests.get(url).content
ppg2014_list = pd.read_html(html)
ppg2014 = ppg2014_list[0]

# Reads in the Opposing team's PPG for each team in 2014
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2014-04-07"

html = requests.get(url).content
oppPpg2014_list = pd.read_html(html)
oppPpg2014 = oppPpg2014_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2014 = oppPpg2014.drop(oppPpg2014.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2014 = oppPpg2014.rename(columns={'2013': 'OppPPG'})

ppg2014 = ppg2014.drop(ppg2014.columns[[0,3,4,5,6,7]], axis=1)
ppg2014 = ppg2014.rename(columns={'2013': 'PPG'})

# Reads in the PPG for each team in 2013
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2013-04-08"

html = requests.get(url).content
ppg2013_list = pd.read_html(html)
ppg2013 = ppg2013_list[0]

# Reads in the Opposing team's PPG for each team in 2013
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2013-04-08"

html = requests.get(url).content
oppPpg2013_list = pd.read_html(html)
oppPpg2013 = oppPpg2013_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2013 = oppPpg2013.drop(oppPpg2013.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2013 = oppPpg2013.rename(columns={'2012': 'OppPPG'})

ppg2013 = ppg2013.drop(ppg2013.columns[[0,3,4,5,6,7]], axis=1)
ppg2013 = ppg2013.rename(columns={'2012': 'PPG'})

# Reads in the PPG for each team in 2012
url = "https://www.teamrankings.com/ncaa-basketball/stat/points-per-game?date=2012-04-02"

html = requests.get(url).content
ppg2012_list = pd.read_html(html)
ppg2012 = ppg2012_list[0]

# Reads in the Opposing team's PPG for each team in 2012
url = "https://www.teamrankings.com/ncaa-basketball/stat/opponent-points-per-game?date=2012-04-02"

html = requests.get(url).content
oppPpg2012_list = pd.read_html(html)
oppPpg2012 = oppPpg2012_list[0]

# Drops the repetitive columns and Renames the meaningful columns
oppPpg2012 = oppPpg2012.drop(oppPpg2012.columns[[0,3,4,5,6,7]], axis=1)
oppPpg2012 = oppPpg2012.rename(columns={'2011': 'OppPPG'})

ppg2012 = ppg2012.drop(ppg2012.columns[[0,3,4,5,6,7]], axis=1)
ppg2012 = ppg2012.rename(columns={'2011': 'PPG'})

# Reads in team names and conferences of teams in NCAA Tournament for 2022
url = "https://en.wikipedia.org/wiki/2022_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2022 = pd.DataFrame()
MMteams2022 = pd.concat([MMteams_list[5], MMteams_list[6], MMteams_list[7], MMteams_list[8]])
MMteams2022 = MMteams2022.reset_index(drop=True)

#Merges ppg2022 and OppPPG2022 as well as standardizing the School Column
points2022 = ppg2022.merge(oppPpg2022)
points2022 = points2022.rename(columns={'Team': 'School'})
points2022['School'] = points2022['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2022
points2022.loc[154, 'School'] = 'New Mexico State'
points2022.loc[217, 'School'] = 'Cal State Fullerton'
points2022.loc[192, 'School'] = "Saint Mary's"
points2022.loc[18, 'School'] = "North Carolina"
points2022.loc[148, 'School'] = "Virginia Tech"
points2022.loc[274, 'School'] = "Saint Peter's"
points2022.loc[223, 'School'] = "TCU"
points2022.loc[110, 'School'] = "Loyola Chicago"
points2022.loc[1, 'School'] = "South Dakota State"
points2022.loc[158, 'School'] = "Jacksonville State"
points2022.loc[205, 'School'] = "Texas Southern"
points2022.loc[78, 'School'] = "Texas A&M–Corpus Christi"

# Creates a dataframe for all 2022 data
MMteams2022 = pd.merge(MMteams2022, points2022)
MMteams2022['year'] = 2022

# Reads in team names and conferences of teams in NCAA Tournament for 2021
url = "https://en.wikipedia.org/wiki/2021_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2021 = pd.DataFrame()
MMteams2021 = pd.concat([MMteams_list[4], MMteams_list[5], MMteams_list[6], MMteams_list[7]])
MMteams2021 = MMteams2021.reset_index(drop=True)

#Merges ppg2021 and OppPPG2021 as well as standardizing the School Column
points2021 = ppg2021.merge(oppPpg2021)
points2021 = points2021.rename(columns={'Team': 'School'})
points2021['School'] = points2021['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2021
points2021.loc[90, 'School'] = 'UC Santa Barbara'
points2021.loc[23, 'School'] = 'Eastern Washington'
points2021.loc[192, 'School'] = "Grand Canyon"
points2021.loc[249, 'School'] = "Appalachian State"
points2021.loc[137, 'School'] = "UConn"
points2021.loc[179, 'School'] = "St. Bonaventure"
points2021.loc[103, 'School'] = "UNC Greensboro"
points2021.loc[81, 'School'] = "Abilene Christian"
points2021.loc[323, 'School'] = "Mount St. Mary's"
points2021.loc[107, 'School'] = "Texas Southern"
points2021.loc[58, 'School'] = "North Carolina"
points2021.loc[130, 'School'] = "Virginia Tech"
points2021.loc[30, 'School'] = "West Virginia"
points2021.loc[176, 'School'] = "Loyola Chicago"
points2021.loc[64, 'School'] = "Georgia Tech"

# Creates a dataframe for all 2021 data
MMteams2021 = pd.merge(MMteams2021, points2021)
MMteams2021['year'] = 2021

# Reads in team names and conferences of teams in NCAA Tournament for 2019
url = "https://en.wikipedia.org/wiki/2019_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2019 = pd.DataFrame()
MMteams2019 = pd.concat([MMteams_list[4], MMteams_list[5], MMteams_list[6], MMteams_list[7]])
MMteams2019 = MMteams2019.reset_index(drop=True)

#Merges ppg2019 and OppPPG2019 as well as standardizing the School Column
points2019 = ppg2019.merge(oppPpg2019)
points2019 = points2019.rename(columns={'Team': 'School'})
points2019['School'] = points2019['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2019
points2019.loc[125, 'School'] = "Virginia Tech"
points2019.loc[50, 'School'] = 'Mississippi State'
points2019.loc[150, 'School'] = 'UCF'
points2019.loc[276, 'School'] = "North Carolina Central"
points2019.loc[154, 'School'] = "North Dakota State"
points2019.loc[53, 'School'] = "St. John's"
points2019.loc[52, 'School'] = "Northern Kentucky"
points2019.loc[102, 'School'] = "Fairleigh Dickinson"
points2019.loc[90, 'School'] = "Prairie View A&M"
points2019.loc[81, 'School'] = "Ole Miss"
points2019.loc[147, 'School'] = "Saint Mary's"
points2019.loc[86, 'School'] = "Gardner–Webb"
points2019.loc[2, 'School'] = "North Carolina"
points2019.loc[45, 'School'] = "New Mexico State"
points2019.loc[78, 'School'] = "Northeastern"
points2019.loc[207, 'School'] = "Abilene Christian"

# Creates a dataframe for all 2018 data
MMteams2019 = pd.merge(MMteams2019, points2019)
MMteams2019['year'] = 2019

# Reads in team names and conferences of teams in NCAA Tournament for 2018
url = "https://en.wikipedia.org/wiki/2018_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2018 = pd.DataFrame()
MMteams2018 = pd.concat([MMteams_list[3], MMteams_list[4], MMteams_list[5], MMteams_list[6]])
MMteams2018 = MMteams2018.reset_index(drop=True)

#Merges ppg2018 and OppPPG2018 as well as standardizing the School Column
points2018 = ppg2018.merge(oppPpg2018)
points2018 = points2018.rename(columns={'Team': 'School'})
points2018['School'] = points2018['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2018
points2018.loc[231, 'School'] = "Loyola Chicago"
points2018.loc[216, 'School'] = "UMBC"
points2018.loc[21, 'School'] = 'North Carolina'
points2018.loc[11, 'School'] = "South Dakota State"
points2018.loc[208, 'School'] = "UNC Greensboro"
points2018.loc[253, 'School'] = "North Carolina Central"
points2018.loc[64, 'School'] = "Texas Southern"
points2018.loc[36, 'School'] = "West Virginia"
points2018.loc[38, 'School'] = "Virginia Tech"
points2018.loc[70, 'School'] = "St. Bonaventure"
points2018.loc[62, 'School'] = "Stephen F. Austin"
points2018.loc[211, 'School'] = "Cal State Fullerton"
points2018.loc[83, 'School'] = "LIU Brooklyn"
points2018.loc[17, 'School'] = "TCU"
points2018.loc[105, 'School'] = "New Mexico State"
points2018.loc[122, 'School'] = "College of Charleston"
points2018.loc[109, 'School'] = "Penn"

# Creates a dataframe for all 2018 data
MMteams2018 = pd.merge(MMteams2018, points2018)
MMteams2018['year'] = 2018

# Reads in team names and conferences of teams in NCAA Tournament for 2017
url = "https://en.wikipedia.org/wiki/2017_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2017 = pd.DataFrame()
MMteams2017 = pd.concat([MMteams_list[3], MMteams_list[4], MMteams_list[5], MMteams_list[6]])
MMteams2017 = MMteams2017.reset_index(drop=True)

#Merges ppg2017 and OppPPG2017 as well as standardizing the School Column
points2017 = ppg2017.merge(oppPpg2017)
points2017 = points2017.rename(columns={'Team': 'School'})
points2017['School'] = points2017['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2017
points2017.loc[130, 'School'] = "SMU"
points2017.loc[170, 'School'] = "South Carolina"
points2017.loc[39, 'School'] = 'Virginia Tech'
points2017.loc[13, 'School'] = "UNC Wilmington"
points2017.loc[37, 'School'] = "East Tennessee State"
points2017.loc[62, 'School'] = "New Mexico State"
points2017.loc[284, 'School'] = "Mount St. Mary's"
points2017.loc[329, 'School'] = "Jacksonville State"
points2017.loc[165, 'School'] = "North Carolina Central"
points2017.loc[18, 'School'] = "West Virginia"
points2017.loc[187, 'School'] = "Saint Mary's"
points2017.loc[77, 'School'] = "Florida Gulf Coast"
points2017.loc[85, 'School'] = "South Dakota State"
points2017.loc[8, 'School'] = "North Carolina"
points2017.loc[135, 'School'] = "Middle Tennessee"
points2017.loc[120, 'School'] = "Northern Kentucky"
points2017.loc[136, 'School'] = "Texas Southern"

# Creates a dataframe for all 2017 data
MMteams2017 = pd.merge(MMteams2017, points2017)
MMteams2017['year'] = 2017

# Reads in team names and conferences of teams in NCAA Tournament for 2016
url = "https://en.wikipedia.org/wiki/2016_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2016 = pd.DataFrame()
MMteams2016 = pd.concat([MMteams_list[3], MMteams_list[4], MMteams_list[5], MMteams_list[6]])
MMteams2016 = MMteams2016.reset_index(drop=True)

#Merges ppg2016 and OppPPG2016 as well as standardizing the School Column
points2016 = ppg2016.merge(oppPpg2016)
points2016 = points2016.rename(columns={'Team': 'School'})
points2016['School'] = points2016['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2016
points2016.loc[102, 'School'] = "Miami"
points2016.loc[157, 'School'] = "UConn"
points2016.loc[96, 'School'] = 'South Dakota State'
points2016.loc[137, 'School'] = "UNC Asheville"
points2016.loc[61, 'School'] = "Saint Joseph's"
points2016.loc[266, 'School'] = "Northern Iowa"
points2016.loc[41, 'School'] = "UNC Wilmington"
points2016.loc[8, 'School'] = "Green Bay"
points2016.loc[187, 'School'] = "Cal State Bakersfield"
points2016.loc[7, 'School'] = "North Carolina"
points2016.loc[35, 'School'] = "West Virginia"
points2016.loc[28, 'School'] = "Stephen F. Austin"
points2016.loc[86, 'School'] = "Florida Gulf Coast"
points2016.loc[74, 'School'] = "Fairleigh Dickinson"
points2016.loc[232, 'School'] = "Little Rock"
points2016.loc[177, 'School'] = "Middle Tennessee"

# Creates a dataframe for all 2016 data
MMteams2016 = pd.merge(MMteams2016, points2016)
MMteams2016['year'] = 2016

# Reads in team names and conferences of teams in NCAA Tournament for 2015
url = "https://en.wikipedia.org/wiki/2015_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2015 = pd.DataFrame()
MMteams2015 = pd.concat([MMteams_list[3], MMteams_list[4], MMteams_list[5], MMteams_list[6]])
MMteams2015 = MMteams2015.reset_index(drop=True)

#Merges ppg2015 and OppPPG2015 as well as standardizing the School Column
points2015 = ppg2015.merge(oppPpg2015)
points2015 = points2015.rename(columns={'Team': 'School'})
points2015['School'] = points2015['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2015
points2015.loc[42, 'School'] = "West Virginia"
points2015.loc[125, 'School'] = "Northeastern"
points2015.loc[156, 'School'] = 'New Mexico State'
points2015.loc[12, 'School'] = "North Carolina"
points2015.loc[133, 'School'] = "Texas Southern"
points2015.loc[71, 'School'] = "Coastal Carolina"
points2015.loc[218, 'School'] = "Northern Iowa"
points2015.loc[78, 'School'] = "North Carolina State"
points2015.loc[105, 'School'] = "SMU"
points2015.loc[74, 'School'] = "St. John's"
points2015.loc[7, 'School'] = "Stephen F. Austin"
points2015.loc[4, 'School'] = "Eastern Washington"
points2015.loc[235, 'School'] = "North Dakota State"
points2015.loc[28, 'School'] = "North Florida"
points2015.loc[111, 'School'] = "Robert Morris"

# Creates a dataframe for all 2015 data
MMteams2015 = pd.merge(MMteams2015, points2015)
MMteams2015['year'] = 2015

# Reads in team names and conferences of teams in NCAA Tournament for 2014
url = "https://en.wikipedia.org/wiki/2014_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

MMteams2014 = pd.DataFrame()
MMteams2014 = pd.concat([MMteams_list[4], MMteams_list[5], MMteams_list[6], MMteams_list[7]])
MMteams2014 = MMteams2014.reset_index(drop=True)

#Merges ppg2014 and OppPPG2014 as well as standardizing the School Column
points2014 = ppg2014.merge(oppPpg2014)
points2014 = points2014.rename(columns={'Team': 'School'})
points2014['School'] = points2014['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2014
points2014.loc[50, 'School'] = "Stephen F. Austin"
points2014.loc[128, 'School'] = "Western Michigan"
points2014.loc[156, 'School'] = 'Eastern Kentucky'
points2014.loc[42, 'School'] = "Mount St. Mary's"
points2014.loc[35, 'School'] = "North Carolina"
points2014.loc[113, 'School'] = "UConn"
points2014.loc[85, 'School'] = "George Washington"
points2014.loc[129, 'School'] = "Saint Joseph's"
points2014.loc[106, 'School'] = "North Carolina Central"
points2014.loc[178, 'School'] = "Milwaukee"
points2014.loc[170, 'School'] = "Coastal Carolina"
points2014.loc[72, 'School'] = "North Dakota State"
points2014.loc[36, 'School'] = "New Mexico State"
points2014.loc[15, 'School'] = "Louisiana-Lafayette"
points2014.loc[60, 'School'] = "Texas Southern"
points2014.loc[44, 'School'] = "Massachusetts"

# Creates a dataframe for all 2014 data
MMteams2014 = pd.merge(MMteams2014, points2014)
MMteams2014['year'] = 2014

# Reads in team names and conferences of teams in NCAA Tournament for 2013
url = "https://en.wikipedia.org/wiki/2013_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html, header=1)

MMteams2013 = pd.DataFrame()
MMteams2013 = pd.concat([MMteams_list[3], MMteams_list[4],MMteams_list[5], MMteams_list[6]])
MMteams2013 = MMteams2013.reset_index(drop=True)

#Merges ppg2013 and OppPPG2013 as well as standardizing the School Column
points2013 = ppg2013.merge(oppPpg2013)
points2013 = points2013.rename(columns={'Team': 'School'})
points2013['School'] = points2013['School'].apply(lambda x: x[:-2] + 'State' if x[-3:] == 'St' else x)

# Renames the teams that conflict with MMteams2013
points2013.loc[15, 'School'] = "North Carolina"
points2013.loc[49, 'School'] = "South Dakota State"
points2013.loc[9, 'School'] = 'Northwestern State'
points2013.loc[51, 'School'] = "Florida Gulf Coast"
points2013.loc[177, 'School'] = "Western Kentucky"
points2013.loc[6, 'School'] = "Ole Miss"
points2013.loc[106, 'School'] = "Miami"
points2013.loc[215, 'School'] = "James Madison"
points2013.loc[2, 'School'] = "Long Island"
points2013.loc[78, 'School'] = "Middle Tennessee"
points2013.loc[29, 'School'] = "Saint Mary's (CA)"
points2013.loc[163, 'School'] = "New Mexico State"
points2013.loc[288, 'School'] = "North Carolina A&T"

# Creates a dataframe for all 2013 data
MMteams2013 = pd.merge(MMteams2013, points2013)
MMteams2013['year'] = 2013

# Reads in team names and conferences of teams in NCAA Tournament for 2012
url = "https://en.wikipedia.org/wiki/2012_NCAA_Division_I_men%27s_basketball_tournament"

html = requests.get(url).content
MMteams_list = pd.read_html(html)

# Resets Column Names since the 2012 webpage gave the tables a header
MMteams2012 = pd.DataFrame()
MMteams_list[4].columns = ['Seed', 'School', 'Conference', 'Record', 'Berth type', 'Overall rank']
MMteams_list[5].columns = ['Seed', 'School', 'Conference', 'Record', 'Berth type', 'Overall rank']
MMteams_list[6].columns = ['Seed', 'School', 'Conference', 'Record', 'Berth type', 'Overall rank']
MMteams_list[7].columns = ['Seed', 'School', 'Conference', 'Record', 'Berth type', 'Overall rank']
MMteams2012 = pd.concat([MMteams_list[4],MMteams_list[5], MMteams_list[6], MMteams_list[7]])
MMteams2012 = MMteams2012.reset_index(drop=True)

#Merges ppg2012 and OppPPG2012 as well as standardizing the School Column
points2012 = ppg2012.merge(oppPpg2012)
points2012 = points2012.rename(columns={'Team': 'School'})
points2012['School'] = points2012['School'].apply(lambda x: x[:-2] + 'State' if x[-2:] == 'St' else x)

# Renames the teams that conflict with MMteams2012
points2012.loc[94, 'School'] = "Southern Miss"
points2012.loc[85, 'School'] = "West Virginia"
points2012.loc[96, 'School'] = 'St. Bonaventure'
points2012.loc[171, 'School'] = "Loyola"
points2012.loc[8, 'School'] = "UNC Asheville"
points2012.loc[2, 'School'] = "North Carolina"
points2012.loc[42, 'School'] = "Saint Mary's"
points2012.loc[324, 'School'] = "South Florida"
points2012.loc[100, 'School'] = "Detroit Mercy"
points2012.loc[13, 'School'] = "New Mexico State"
points2012.loc[141, 'School'] = "Mississippi Valley State"
points2012.loc[233, 'School'] = "Western Kentucky"
points2012.loc[43, 'School'] = "Long Beach State"
points2012.loc[22, 'School'] = "South Dakota State"

# Creates a dataframe for all 2012 data
MMteams2012 = pd.merge(MMteams2012, points2012)
MMteams2012['year'] = 2012

# Combines all data from 2012-2022
MMteams = pd.concat([MMteams2022, MMteams2021, MMteams2019, MMteams2018, MMteams2017, MMteams2016, MMteams2015, MMteams2014, MMteams2013, MMteams2012], ignore_index=True)

# Resets Column names as some did match, and deletes the extra columns
MMteams['Overall Seed'] = MMteams['Overall rank'].combine_first(MMteams['Overall Seed'])
MMteams['Overall Seed'] = MMteams['Overall rank[4]'].combine_first(MMteams['Overall Seed'])
MMteams = MMteams.drop(['Overall rank', 'Coach', 'Overall rank[4]'], axis=1)

# Renames some conferences as different years used different names for the same conference
MMteams['Conference'] = MMteams['Conference'].str.replace('Pac-12', 'Pac–12')
MMteams['Conference'] = MMteams['Conference'].str.replace('ASUN', 'Atlantic Sun')
MMteams['Conference'] = MMteams['Conference'].str.replace('CAA', 'Colonial')
MMteams['Conference'] = MMteams['Conference'].str.replace('Ivy League', 'Ivy')
MMteams['Conference'] = MMteams['Conference'].str.replace('WCC', 'West Coast')
MMteams['Conference'] = MMteams['Conference'].str.replace('Summit League', 'Summit')
MMteams['Conference'] = MMteams['Conference'].str.replace('Conference USA', 'C-USA')
MMteams['Conference'] = MMteams['Conference'].str.replace('NEC', 'Northeast')
MMteams['Conference'] = MMteams['Conference'].str.replace('Mid American', 'MAC')
MMteams['Conference'] = MMteams['Conference'].str.replace('MVC', 'Missouri Valley')
MMteams['Berth type'] = MMteams['Berth type'].str.replace('Auto', 'Automatic')
MMteams['Berth type'] = MMteams['Berth type'].str.replace('Automaticmatic', 'Automatic')
MMteams['Berth type'] = MMteams['Berth type'].str.replace('At–large', 'At-Large')
MMteams['Berth type'] = MMteams['Berth type'].str.replace('At-large', 'At-Large')

# Resets PPG and OppPPG to floats to allow averaging
MMteams['PPG'] = MMteams['PPG'].astype(float)
MMteams['OppPPG'] = MMteams['OppPPG'].astype(float)

# Group by year and calculate the mean of PPG and OppPPG
grouped = MMteams.groupby('year')[['PPG', 'OppPPG']].mean()

# Plot the dual bar chart
grouped.plot(kind='bar', width=0.8, figsize=(8, 6))
plt.xlabel('Year')
plt.ylabel('Points per game')
plt.title('Average PPG and OppPPG by year')
plt.legend(['PPG', 'OppPPG'])
plt.show()

# There is not too significant of a trend on this chart, both averages went up a little in 2017 and 2018, but not too
# significantly, or long enough to consider it a trend.

# Group by year and calculate the mean of PPG and OppPPG
MMteams['Seed'] = MMteams['Seed'].astype(str)

# Removes all *'s and #'s from the Seed Column, and makes Seed a Float
MMteams['Seed'] = MMteams['Seed'].str.replace('*', '')
MMteams['Seed'] = MMteams['Seed'].str.replace('#', '')
MMteams['Seed'] = MMteams['Seed'].astype(float)

# Plot the dual bar chart
avg_seed = MMteams.groupby('Conference')['Seed'].mean()
avg_seed_sorted = avg_seed.sort_values(ascending=False)

# Create a bar chart of the average seed by conference
fig, ax = plt.subplots(figsize=(10, 10))

# plot the bar chart
ax.barh(avg_seed_sorted.index, avg_seed_sorted.values)

# customize the chart
ax.set_title('Average Seed by Conference')
ax.set_xlabel('Conference')
ax.set_ylabel('Average Seed')
ax.tick_params(axis='x', rotation=10)
plt.show()

# There is an obvious jump between the Atlantic 10 and Conference USA on this chart. The reason is likely because the
# conferences below the A10 usually get one sometimes two teams into the tournament, and since their teams are not as good
# as the other conferences their teams struggle to gain a high enough Strength of Schedule to both make the tournament,
# as well as earning top seeds

# Counts how many occurences of each conference are found in the dataset
n = 15
conference_counts = MMteams['Conference'].value_counts()
top_conferences = conference_counts[:n].index.tolist()
MMteams.loc[~MMteams['Conference'].isin(top_conferences), 'Conference'] = '1 Bid Conferences'
conference_counts = MMteams['Conference'].value_counts()

# Plots the resulting Pie Chart
plt.figure(figsize=(8,8))
plt.pie(conference_counts, labels=conference_counts.index, autopct='%1.1f%%')
plt.title('Conference Distribution')
plt.show()

# The 1-bid Conferences were the conferences in which between 2012 and 2022 only had one team each year. An interesting note
# is that the "Power 5" were not the top 5 conferences on the list as the SEC and the Pac-12 both fell underneath the Big
# East in this chart


import streamlit as st
import pandas as pd
import pickle
import time

st.title('Diabnostics')
st.subheader("This diagnostic tool predicts a patient's risk of diabetes")

columns = st.columns(2)
with columns[0]:
    age=st.slider('How old are you?',0,90,16)
with columns[1]:
    gender=st.selectbox('Gender', ['Female','Male'])

st.subheader('Which of these symptoms do you have?')
columns = st.columns(4)
with columns[0]:
    polyuria=st.selectbox('Excessive Peeing',['No','Yes'])
with columns[1]:
    polydipsia=st.selectbox('Extreme Thirst', ['No','Yes'])
with columns[2]:
    sudden_weight_loss=st.selectbox('Sudden Weight Loss',['No','Yes'])
with columns[3]:
    weakness=st.selectbox('Weakness', ['No','Yes'])

columns = st.columns(4)
with columns[0]:
    polyphagia=st.selectbox('Increased Appetite',['No','Yes'])
with columns[1]:
    genital_thrush=st.selectbox('Yeast Infection', ['No','Yes'])
with columns[2]:
    visual_blurring=st.selectbox('Blurry Vision',['No','Yes'])
with columns[3]:
    itching=st.selectbox('Itching', ['No','Yes'])

columns = st.columns(4)
with columns[0]:
    irritability=st.selectbox('Frustration',['No','Yes'])
with columns[1]:
    delayed_healing=st.selectbox('Delayed Healing', ['No','Yes'])
with columns[2]:
    partial_paresis=st.selectbox('Muscle Weakness',['No','Yes'])
with columns[3]:
    muscle_stiffness=st.selectbox('Muscle Stiffness', ['No','Yes'])

columns = st.columns(2)
with columns[0]:
    alopecia=st.selectbox('Hair Loss',['No','Yes'])
with columns[1]:
    obesity=st.selectbox('Obesity', ['No','Yes'])

features = pd.DataFrame([[age,gender,polyuria,polydipsia,sudden_weight_loss,weakness,polyphagia,genital_thrush,visual_blurring,itching,irritability,delayed_healing,partial_paresis,muscle_stiffness,alopecia,obesity]])

# encode categories
features.replace(['Yes','Positive','Male','No','Negative','Female'],[1,1,1,0,0,0],inplace=True)

# load trained model
model = pickle.load(open('model.pkl','rb'))

# predict probability of the case being diabetic
probability = model.predict_proba(features)[:,1][0]
percentage = round(probability*100)

my_bar = st.progress(0)
for percent_complete in range(percentage):
     time.sleep(0.02)
     my_bar.progress(percent_complete + 1)
if percentage<=50:
    st.success(f'You are **{percentage}%** likely to have diabetes')

elif 50<percentage<=75:
    st.warning(f'You are **{percentage}%** likely to have diabetes')

else:
    st.error(f'You are **{percentage}%** likely to have diabetes')


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import gdb
import tempfile
import pprint
import inspect
import sys
import struct
import string
import re
import itertools
import functools
from subprocess import *
import binascii
import config

from codecs import encode, decode

try:    from StringIO import StringIO # Python2
except: from io       import StringIO # Python3

try:    unicode
except: unicode = str

# http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
# http://stackoverflow.com/questions/8856164/class-decorator-decorating-method-in-python
class memoized(object):
    """
    Decorator. Caches a function's return value each time it is called.
    If called later with the same arguments, the cached value is returned
    (not reevaluated).
    """
    def __init__(self, func):
        self.func = func
        self.instance = None # bind with instance class of decorated method
        self.cache = {}
        self.__doc__ = inspect.getdoc(self.func)

    def __call__(self, *args, **kwargs):
        try:
            return self.cache[(self.func, self.instance, args) + tuple(kwargs.items())]
        except KeyError:
            if self.instance is None:
                value = self.func(*args, **kwargs)
            else:
                value = self.func(self.instance, *args, **kwargs)
            self.cache[(self.func, self.instance, args) + tuple(kwargs.items())] = value
            return value
        except TypeError:
            # uncachable -- for instance, passing a list as an argument.
            # Better to not cache than to blow up entirely.
            if self.instance is None:
                return self.func(*args, **kwargs)
            else:
                return self.func(self.instance, *args, **kwargs)

    def __repr__(self):
        """Return the function's docstring."""
        return self.__doc__

    def __get__(self, obj, objtype):
        """Support instance methods."""
        if obj is None:
            return self
        else:
            self.instance = obj
            return self

    def _reset(self):
        """Reset the cache"""
        for cached in list(self.cache.keys()):
            if cached[0] == self.func and cached[1] == self.instance:
                del self.cache[cached]

def reset_cache(module=None):
    """
    Reset memoized caches of an instance/module
    """
    if module is None:
        module = sys.modules['__main__']

    for m in dir(module):
        m = getattr(module, m)
        if isinstance(m, memoized):
            m._reset()
        else:
            for f in dir(m):
                f = getattr(m, f)
                if isinstance(f, memoized):
                    f._reset()

    return True

def tmpfile(pref="peda-"):
    """Create and return a temporary file with custom prefix"""
    return tempfile.NamedTemporaryFile(prefix=pref)

def colorize(text, color=None, attrib=None):
    """
    Colorize text using ansicolor
    ref: https://github.com/hellman/libcolors/blob/master/libcolors.py
    """
    # ansicolor definitions
    COLORS = {"black": "30", "red": "31", "green": "32", "yellow": "33",
                "blue": "34", "purple": "35", "cyan": "36", "white": "37"}
    CATTRS = {"regular": "0", "bold": "1", "underline": "4", "strike": "9",
                "light": "1", "dark": "2", "invert": "7"}

    CPRE = '\033['
    CSUF = '\033[0m'

    if not config.Option.get("ansicolor"):
        return text

    ccode = ""
    if attrib:
        for attr in attrib.lower().split():
            attr = attr.strip(",+|")
            if attr in CATTRS:
                ccode += ";" + CATTRS[attr]
    if color in COLORS:
        ccode += ";" + COLORS[color]
    return CPRE + ccode + "m" + text + CSUF

def green(text, attrib=None):
    """Wrapper for colorize(text, 'green')"""
    return colorize(text, "green", attrib)

def red(text, attrib=None):
    """Wrapper for colorize(text, 'red')"""
    return colorize(text, "red", attrib)

def yellow(text, attrib=None):
    """Wrapper for colorize(text, 'yellow')"""
    return colorize(text, "yellow", attrib)

def blue(text, attrib=None):
    """Wrapper for colorize(text, 'blue')"""
    return colorize(text, "blue", attrib)

class message(object):
    """
    Generic pretty printer with redirection.
    It also suports buffering using bufferize() and flush().
    """

    def __init__(self):
        self.out = sys.stdout
        self.buffering = 0

    def bufferize(self, f=None):
        """Activate message's bufferization, can also be used as a decorater."""
        return
        if f != None:
            @functools.wraps(f)
            def wrapper(*args, **kwargs):
                self.bufferize()
                f(*args, **kwargs)
                self.flush()
            return wrapper

        # If we are still using stdio we need to change it.
        if not self.buffering:
            self.out = StringIO()
        self.buffering += 1

    def flush(self):
        if not self.buffering:
            raise ValueError("Tried to flush a message that is not bufferising.")
        self.buffering -= 1

        # We only need to flush if this is the lowest recursion level.
        if not self.buffering:
            self.out.flush()
            sys.stdout.write(self.out.getvalue())
            self.out = sys.stdout

    def __call__(self, text, color=None, attrib=None, teefd=None):
        if not teefd:
            teefd = config.Option.get("_teefd")

        if (isinstance(text, str) or isinstance(text, unicode)):
            text = text.replace("\x00", colorize(".", "red", None))
            print(colorize(text, color, attrib), file=self.out)
            if teefd:
                print(colorize(text, color, attrib), file=teefd)
        else:
            pprint.pprint(text, self.out)
            if teefd:
                pprint.pprint(text, teefd)

msg = message()

def warning_msg(text):
    """Colorize warning message with prefix"""
    msg(colorize("Warning: " + str(text), "yellow"))

def error_msg(text):
    """Colorize error message with prefix"""
    msg(colorize("Error: " + str(text), "red"))

def debug_msg(text, prefix="Debug"):
    """Colorize debug message with prefix"""
    if config.Option.get("debug"):
        msg(colorize("%s: %s" % (prefix, str(text)), "cyan"))

def trim(docstring):
    """
    Handle docstring indentation, ref: PEP257
    """
    if not docstring:
        return ''
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = sys.maxsize
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < sys.maxsize:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    # Strip off trailing and leading blank lines:
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    # Return a single string:
    return '\n'.join(trimmed)

def separator(title = ''):
    import struct, termios, fcntl, sys
    try:
        _height, width = struct.unpack('hh', fcntl.ioctl(sys.stdin.fileno(), termios.TIOCGWINSZ, '1234'))
    except:
        width = 80
    w = width - 2 - len(title)
    return '[%s%s%s]' % ('-' * (w // 2), title, '-' * ((w + 1) // 2))

def pager(text, pagesize=None):
    """
    Paging output, mimic external command less/more
    """
    if not pagesize:
        pagesize = config.Option.get("pagesize")

    if pagesize <= 0:
        msg(text)
        return

    i = 1
    text = text.splitlines()
    l = len(text)

    for line in text:
        msg(line)
        if i % pagesize == 0:
            ans = input("--More--(%d/%d)" % (i, l))
            if ans.lower().strip() == "q":
                break
        i += 1

    return

def execute_external_command(command, cmd_input=None):
    """
    Execute external command and capture its output

    Args:
        - command (String)

    Returns:
        - output of command (String)
    """
    result = ""
    P = Popen([command], stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
    (result, err) = P.communicate(cmd_input)
    if err and config.Option.get("debug"):
        warning_msg(err)

    return result.decode()

def is_printable(text, printables=""):
    """
    Check if a string is printable
    """
    try:    text = text.decode('ascii')
    except: return False

    if all(c in string.printable for c in text):
        return True

    return False

def is_math_exp(str):
    """
    Check if a string is a math exprssion
    """
    charset = set("0123456789abcdefx+-*/%^")
    opers = set("+-*/%^")
    exp = set(str.lower())
    return (exp & opers != set()) and (exp - charset == set())

def normalize_argv(args, size=0, convert=True):
    """
    Normalize argv to list with predefined length
    """
    args = list(args)
    for (idx, val) in enumerate(args[:size]):
        if convert:
            as_int = to_int(val)
            if as_int is not None:
                args[idx] = as_int

    args += [None]*(size-len(args))
    return args

def to_hexstr(str):
    """
    Convert a string to hex escape represent
    """
    return "".join(["\\x%02x" % ord(i) for i in str])

def to_hex(num):
    """
    Convert a number to hex format
    """
    if num < 0:
        return "-0x%x" % (-num)
    else:
        return "0x%x" % num

def to_address(num):
    """
    Convert a number to address format in hex
    """
    if num < 0:
        return to_hex(num)
    if num > 0xffffffff: # 64 bit
        return "0x%016x" % num
    else:
        return "0x%08x" % num

def to_int(val):
    """
    Convert a string to int number
    """
    try:    return int(str(val), 0)
    except: pass

    try:    return int(gdb.parse_and_eval(val))
    except: pass

    return None

def str2hex(str):
    """
    Convert a string to hex encoded format
    """
    result = binascii.hexlify(str)
    return result

def hex2str(hexnum, intsize=4, cut=False):
    """
    Convert a number in hex format to string
    """

    if isinstance(hexnum, int):
        nbits = intsize * 8
        hexnum = "0x%x" % ((hexnum + (1 << nbits)) % (1 << nbits))

    s = hexnum[2:]
    if len(s) % 2 != 0:
        s = "0" + s
    result = binascii.unhexlify(s)[::-1]

    if cut:
        pos = result.find(b'\0')
        if pos > 0:
            result = result[0:pos]

    return result

def int2hexstr(num, intsize=4):
    """
    Convert a number to hexified string
    """

    if intsize == 8:
        if num < 0:
            result = struct.pack("<q", num)
        else:
            result = struct.pack("<Q", num)
    else:
        if num < 0:
            result = struct.pack("<l", num)
        else:
            result = struct.pack("<L", num)
    return result

def list2hexstr(intlist, intsize=4):
    """
    Convert a list of number/string to hexified string
    """
    result = ""
    for value in intlist:
        if isinstance(value, str):
            result += value
        else:
            result += int2hexstr(value, intsize)
    return result

def str2intlist(data, intsize=4):
    """
    Convert a string to list of int
    """
    result = []
    data = decode(data,'string_escape')[::-1]
    l = len(data)
    data = ("\x00" * (intsize - l%intsize) + data) if l%intsize != 0 else data
    for i in range(0, l, intsize):
        if intsize == 8:
            val = struct.unpack(">Q", data[i:i+intsize])[0]
        else:
            val = struct.unpack(">L", data[i:i+intsize])[0]
        result = [val] + result
    return result

@memoized
def check_badchars(data, chars=None):
    """
    Check an address or a value if it contains badchars
    """
    if to_int(data) is None:
        to_search = data
    else:
        data = to_hex(to_int(data))[2:]
        if len(data) % 2 != 0:
            data = "0" + data
        to_search = decode(data,'hex')

    if not chars:
        chars = config.Option.get("badchars")

    if chars:
        for c in chars:
            if c in to_search:
                return True
    return False

@memoized
def format_address(addr, type):
    """Colorize an address"""
    colorcodes = {
        "data": "blue",
        "code": "red",
        "rodata": "green",
        "stack": "purple",
        "heap": "purple",
        "value": None
    }
    colorattr = {
        "data": None,
        "code": None,
        "rodata": None,
        "stack": None,
        "heap": "light",
        "value": None
    }

    return colorize(addr, colorcodes[type], colorattr[type])

@memoized
def format_reference_chain(chain):
    """
    Colorize a chain of references

    v = value
    t = type
    vn = value name (str)
    """
    v = t = vn = None
    text = ""

    def safe_escape(text):
        if '"' in text:
            escaped = ''
            for v in bytearray(text.encode('utf-8')):
                if v < 0x20 or v > 0x7e:
                    escaped += '\\%o' % v
                else:
                    escaped += chr(v)
            return escaped
        else:
            return text

    if not chain:
        text += "Cannot access memory address"
    else:
        first = 1
        for (v, t, vn) in chain:
            if t != "value":
                text += "%s%s " % ("--> " if not first else "", format_address(v, t))
            else:
                text += "%s%s " % ("--> " if not first else "", v)
            first = 0

        if vn:
            text += "(%s)" % safe_escape(vn)
        else:
            if v != "0x0" and v != "...":
                s = hex2str(v, cut=True)
                if is_printable(s, "\x00"):
                    r = repr(s)
                    if r.startswith("b'"):
                        r = r[2:-1]
                    else:
                        r = r[1:-1]
                    text += '("%s")' % r
    return text

def split_disasm_line(line):
    # example lines
    # '   0x41ea8a <main+10>:  sub    $0x128,%rsp'
    # '=> 0x8048560:\tmov    eax,ds:0x80499e0 ; hello world
    rprefix   = r'(.*?)'
    raddr     = r'(0x[0-9a-fA-F]+)'
    rname     = r'\s*(?:<(.*?)>)?'
    rinstr    = r':?\s*([^;]+)'
    rcomment  = r'(.*)'
    pattern = rprefix + raddr + rname + rinstr + rcomment

    # PANIC!
    p,a,n,i,c = re.match(pattern, line).groups()

    return p,int(a,16),n,i,(c or None)

# vulnerable C functions, source: rats/flawfinder
VULN_FUNCTIONS = [
    "exec", "system", "gets", "popen", "getenv", "strcpy", "strncpy", "strcat", "strncat",
    "memcpy", "bcopy", "printf", "sprintf", "snprintf", "scanf",  "getchar", "getc", "read",
    "recv", "tmp", "temp"
]

def format_disasm_code(code, nearby=None, coloraddr=None):
    """
    Format output of disassemble command with colors to highlight:
        - dangerous functions (rats/flawfinder)
        - branching: jmp, call, ret
        - testing: cmp, test

    Args:
        - code: input asm code (String)
        - nearby: address for nearby style format (Int)

    Returns:
        - colorized text code (String)
    """
    colorcodes = {
        "cmp": "red",
        "test": "red",
        "call": "green",
        "j": "yellow", # jump
        "ret": "blue",
    }
    result = ""

    if not code:
        return result

    if to_int(nearby) is not None:
        target = to_int(nearby)
    else:
        target = 0

    for line in code.splitlines():
        if ":" not in line or "Dump of assembler code" in line: # not an assembly line
            result += line + "\n"
        else:
            color = style = None

            prefix, addr, name, inst, comment = split_disasm_line(line)
            if not addr:
                result += line + "\n"
                return

            oaddr = re.search("\s*(0x[0-9a-fA-F]+)", line).group(1)
            if coloraddr and addr in coloraddr:
                oaddr = colorize(oaddr, "red", "underline")

            opcode = inst.split(None, 1)[0]
            for c in colorcodes:
                if c not in opcode:
                    continue
                color = colorcodes[c]
                if c == "call":
                    if any(f in inst for f in VULN_FUNCTIONS):
                        style = "bold, underline"
                        color = "red"
                break

            if addr < target:
                style = "dark"
            elif addr == target:
                style = "bold"
                color = "green"

            code = colorize(inst, color, style)

            if name is not None:
                name = colorize(" <%s>" % name, color, "dark")
            else:
                name = ""

            if comment is not None:
                comment = colorize(";" + comment, color, "dark")
            else:
                comment = ""

            line = "%s%s%s:\t%s%s" % (prefix, oaddr, name, code, comment)
            result += line + "\n"

    return result.rstrip()

def split_back(s, sep, maxsplit=-1):
    return [ss[::-1] for ss in s[::-1].split(sep[::-1], maxsplit)][::-1]


from random import randint, choices

VOLEWELS = 'аеиоуяюёэы'
CONSONANTS = ''.join([chr(char) for char in range(ord('а'), ord('я') + 1) if chr(char) not in VOLEWELS])

def make_random_name(amount_of_names: int):
    count = 0
    all_names = []
    while count != amount_of_names:
        word_len = randint(4, 7)
        word = choices(VOLEWELS + CONSONANTS, k=word_len)
        if any(ch in VOLEWELS for ch in word):
            all_names.append(''.join(word).capitalize() + '\n')
            count += 1
    with open('task_2.txt', 'a', encoding='utf-8') as f:
        f.writelines(all_names)

make_random_name(10)


"""
Title: Augmented Warfighter Awareness System Display
Author: Bryan Ritchie
Team: UCCS Senior Design "Heads Up" 2020

Purpose: This file is intended as a driver for the 2.8" TFT display,
         to display the "real-time" simulated sensor data.

"""
import time
from multiprocessing import Value
import os
#from main import sensorData

RUN = 0
DEMO = 1

# Change this runmode to run as a standalone demo
# This is useful when modifying the layout of the display
RUNMODE = RUN

### <<< SCREEN LAYOUT >>> ###
#< COLUMNS >#
TITLE_START             =   10
SAMPLE_START            =   4
WARRIOR_NAME_START      =   14
WARRIOR_NAME_SPACING    =   13
DATA_NAME_START         =   4
DATA_START              =   WARRIOR_NAME_START + 3
DATA_SPACING            =   WARRIOR_NAME_SPACING
CONNECTION_STATUS_START =   4
CLIENT_MESSAGE_START    =   3

#< ROWS >#
TITLE_ROW               =   3
SAMPLE_ROW              =   TITLE_ROW + 1
WARRIOR_NAME_ROW        =   TITLE_ROW + 2
AMMO_ROW                =   TITLE_ROW + 3
WATER_ROW               =   TITLE_ROW + 4
HR_ROW                  =   TITLE_ROW + 5
SPO2_ROW                =   TITLE_ROW + 6
TEMP_ROW                =   TITLE_ROW + 7
RESP_ROW                =   TITLE_ROW + 8
WEAPON_ROW              =   TITLE_ROW + 9
CONNECTION_STATUS_ROW   =   3
CLIENT_MESSAGE_ROW      =   WEAPON_ROW + 2

#< CLIENT MESSAGE >#
MAX_MESSAGE_LENGTH      =   49
MAX_MESSAGE_LINES       =   5

### <<< SENSOR DATA >>> ###
#< SENSOR DATA ELEMENTS>#
WARRIOR_TOTAL           =   3
HIGH                    =   1
LOW                     =   0

ID_DATA                 =   0
AMMO_DATA               =   1
WATER_DATA              =   2
VITALS_DATA             =   3
HR_DATA                 =   0
SPO2_DATA               =   1
TEMP_DATA               =   2
RESP_DATA               =   3
WEAPON_DATA             =   4

# AMMO COLOR STATUS >#
# Units are in Rounds of Ammunition
AMMO_GREEN              =   270
AMMO_AMBER              =   202
AMMO_RED                =   135
AMMO_BLACK              =   68   # Black doesn't show up well, so it will be blue

# WATER COLOR STATUS >#
# Units are in Quarts
WATER_GREEN             =   3
WATER_AMBER             =   2
WATER_RED               =   1
WATER_BLACK             =   0

#< VITALS COLOR STATUS >#
#<< HR >>#
# Units: Beats per Minute   [LOW, HIGH]
HR_GREEN                =   [60, 100]
HR_AMBER                =   [50, 120]
HR_RED                  =   [40, 160]
HR_BLACK                =   [30, 200]

#<< SPO2 >>#
SPO2_GREEN              =   100
SPO2_AMBER              =   92
SPO2_RED                =   85
SPO2_BLACK              =   80

#<< RESPIRATIONS >>#
# Units: Breaths per min    [LOW, HIGH]
RESP_GREEN              =   [12, 15]
RESP_AMBER              =   [10, 18]
RESP_RED                =   [8, 21]
RESP_BLACK              =   [0, 25]

#<< TEMP >>#
# Units: Degrees F          [LOW, HIGH]
TEMP_GREEN              =   [96, 99]
TEMP_AMBER              =   [93, 101]
TEMP_RED                =   [85, 103]
TEMP_BLACK              =   [80, 104]

#< WEAPON COLOR STATUS >#
# WEAPON ON SAFE: Even Number
# WEAPON ON FIRE: Odd Number
# [SECONDS SINCE FIRING + SAFETY]
WEAPON_GREEN            = 0         # Has not fired, weapon on safe
WEAPON_AMBER            = 1         # Has not fired, weapon on fire
WEAPON_RED              = 11        # Been at least 10 seconds since last firing (weapon on safe or fire)
WEAPON_BLACK            = [2, 11]   # Been 2 - 10 just a short time since firing (weapon on safe or fire)

### <<< TFT NAVIGATION >>> ###
def moveCursor(row, col):
    print(chr(27) + "[" + str(row) + ";" + str(col) + "f")

def clearScreen():
    moveCursor(1,1)
    print(chr(27) + "[2J")

def hideCursor():
    print("\033[?25h")

# Print at a certain location on the TFT Screen
def print_at(row, col, message):
    print(chr(27) + "[" + str(row) + ";" + str(col) + "f" + message)

### <<< HANDLE TFT MESSAGE PRINTING >>> ###
class MessagePrintService(object):
    def __init__(self):
        self.messageLines = [None] * MAX_MESSAGE_LINES

        self.colorText_Mutex = Value("i", 0)

        self.messageColor   = "red"
        self.warriorColor   = "white"
        self.dataNameColor  = "white"
        self.dataColor      = "white"
        self.titleColor     = "green"
        self.borderColor    = "white"

        self.sample_counter = 0
        self.delay_counter   = 0

    def displayStructure(self):
        #< BORDER >#
        moveCursor(1,1)
        self.colorText(self.borderColor)
        print("*****************************************************")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*                                                   *")
        print("*****************************************************")

        #< TITLE >#
        self.colorText(self.titleColor)
        print_at(TITLE_ROW, TITLE_START, "AUGMENTED WARFIGHTER AWARENESS SYSTEM")

        #< WARRIOR LABELS >#
        self.colorText(self.warriorColor)
        print_at(WARRIOR_NAME_ROW, WARRIOR_NAME_START,  "Warrior 1")
        print_at(WARRIOR_NAME_ROW, WARRIOR_NAME_START + WARRIOR_NAME_SPACING,  "Warrior 2")
        print_at(WARRIOR_NAME_ROW, WARRIOR_NAME_START + WARRIOR_NAME_SPACING * 2,  "Warrior 3")

        #< SENSOR LABELS >#
        self.colorText(self.dataNameColor)
        print_at(AMMO_ROW, DATA_NAME_START,     "Ammo   :")
        print_at(WATER_ROW, DATA_NAME_START,    "Water  :")
        print_at(HR_ROW, DATA_NAME_START,       "HR     :")
        print_at(SPO2_ROW, DATA_NAME_START,     "SPO2   :")
        print_at(TEMP_ROW, DATA_NAME_START,     "Temp   :")
        print_at(RESP_ROW, DATA_NAME_START,     "Resp   :")
        print_at(WEAPON_ROW, DATA_NAME_START,   "Weapon :")

    def clearMessagePane(self):
        self.colorText(self.borderColor)
        print_at(CLIENT_MESSAGE_ROW, CLIENT_MESSAGE_START, "                                                   ")
        self.colorText(self.borderColor)
        print_at(CLIENT_MESSAGE_ROW + 1, 1,                "*                                                   *")
        self.colorText(self.borderColor)
        print_at(CLIENT_MESSAGE_ROW + 2, 1,                "*                                                   *")
        self.colorText(self.borderColor)
        print_at(CLIENT_MESSAGE_ROW + 3, 1,                "*                                                   *")
        self.colorText(self.borderColor)
        print_at(CLIENT_MESSAGE_ROW + 4, 1,                "*                                                   *")

    def shiftMessagePane(self, numLines):

        # Shift Messages
        for i in range(numLines):
            for j in range(MAX_MESSAGE_LINES - 1, 0, -1):
                self.messageLines[j] = self.messageLines[j - 1]

        # Re-print messages
        for k in range(MAX_MESSAGE_LINES):
            if(self.messageLines[k] is not None):
                self.colorText(self.borderColor)
                print_at(CLIENT_MESSAGE_ROW + k, CLIENT_MESSAGE_START, "                                                  *")
                self.colorText(self.messageColor)
                print_at(CLIENT_MESSAGE_ROW + k, CLIENT_MESSAGE_START, self.messageLines[k])

    def printClientMessage(self, message):
        # Add concatenated timestamp to message
        message = "[" + str(int(time.time()) & 0xFFF) + "]: " + str(message)

        # Check length of message
        messageLength = len(message)
        messagesRequired = 1

        # If message is too long, count how many messages will be needed?
        while(messageLength > MAX_MESSAGE_LENGTH):
            messagesRequired += 1
            messageLength -= MAX_MESSAGE_LENGTH

        # Shift the message pane to make room for new messages
        self.shiftMessagePane(messagesRequired)

        # Clear the first message row (Bugfix)
        self.colorText(self.borderColor)
        print_at(CLIENT_MESSAGE_ROW, CLIENT_MESSAGE_START, "                                                  *")

        # Change the pen color to messageColor
        self.colorText(self.messageColor)

        # Create a messages list to split the messages into
        if(messagesRequired > 1):
            # Re-discover message length
            messageLength = len(message)

            # Track how many messages have been parsed
            messagesParsed = 0

            while(messagesParsed < messagesRequired and messageLength > MAX_MESSAGE_LENGTH) and messagesParsed < MAX_MESSAGE_LINES:

                # Store message to messageLines (for shifting purposes)
                self.messageLines[messagesParsed] = str(message[ messagesParsed*MAX_MESSAGE_LENGTH : (messagesParsed + 1)*MAX_MESSAGE_LENGTH ])

                # Print the message that was stored
                print_at(CLIENT_MESSAGE_ROW + messagesParsed, CLIENT_MESSAGE_START, self.messageLines[messagesParsed])

                # Iterate how many messages have been parsed
                messagesParsed += 1

                # Reduce remaining message length to be parsed
                messageLength -= MAX_MESSAGE_LENGTH

            # Check if there is any leftover message
            if(messageLength > 0 and messagesParsed < MAX_MESSAGE_LINES):
                # Store the message to messageLines (for shifting purposes)
                self.messageLines[messagesParsed] = str(message[ messagesParsed*MAX_MESSAGE_LENGTH : len(message) ])

                # Print the message that was stored
                print_at(CLIENT_MESSAGE_ROW + messagesParsed, CLIENT_MESSAGE_START, self.messageLines[messagesParsed])

        else:
            # Just print the single message
            self.messageLines[0] = str(message)
            print_at(CLIENT_MESSAGE_ROW, CLIENT_MESSAGE_START, self.messageLines[0])

    def displayData(self, connectionStatus, sensorData_packages):
        while(1):
            # Iterate through the sample data
            if(self.sample_counter < 3):

                # Apply a delay to make the changing data observable
                if(self.delay_counter >= 2000):
                    self.sample_counter += 1
                    self.delay_counter = 0 # cyclic reset
                else:
                    self.delay_counter += 1
            else:
                self.sample_counter = 0 # cyclic reset

            # redundant check (Bugfix)
            if(self.sample_counter == 3):
                self.sample_counter = 0

            # Select the current sample data
            sensorData = sensorData_packages[self.sample_counter]

            #< AMMO >#
            # Determine Color Status
            for i in range(WARRIOR_TOTAL):
                if(sensorData[i][AMMO_DATA] > AMMO_AMBER and sensorData[i][AMMO_DATA] <= AMMO_GREEN):
                    self.colorText("green")
                elif(sensorData[i][AMMO_DATA] > AMMO_RED and sensorData[i][AMMO_DATA] <= AMMO_AMBER):
                    self.colorText("yellow")
                elif(sensorData[i][AMMO_DATA] > AMMO_BLACK and sensorData[i][AMMO_DATA] <= AMMO_RED):
                    self.colorText("red")
                elif(sensorData[i][AMMO_DATA] <= AMMO_BLACK):
                    self.colorText("blue")

                # Print Data
                print_at(AMMO_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][AMMO_DATA]) + "   ")

            #< WATER >#
            for i in range(WARRIOR_TOTAL):
                # Determine Color Status
                if(sensorData[i][WATER_DATA] > WATER_AMBER):
                    self.colorText("green")
                elif(sensorData[i][WATER_DATA] > WATER_RED and sensorData[i][WATER_DATA] <= WATER_AMBER):
                    self.colorText("yellow")
                elif(sensorData[i][WATER_DATA] > WATER_BLACK and sensorData[i][WATER_DATA] <= WATER_RED):
                    self.colorText("red")
                elif(sensorData[i][WATER_DATA] <= WATER_BLACK):
                    self.colorText("blue")

                # Print Data
                print_at(WATER_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][WATER_DATA]) + "   ")

            #< HR >#
            for i in range(WARRIOR_TOTAL):
                # Determine Color Status
                if(sensorData[i][VITALS_DATA][HR_DATA] >= HR_GREEN[LOW] and sensorData[i][VITALS_DATA][HR_DATA] <= HR_GREEN[HIGH]):
                    self.colorText("green")
                elif((sensorData[i][VITALS_DATA][HR_DATA] >= HR_AMBER[LOW] and sensorData[i][VITALS_DATA][HR_DATA] < HR_GREEN[LOW]) or \
                    (sensorData[i][VITALS_DATA][HR_DATA] > HR_GREEN[HIGH] and sensorData[i][VITALS_DATA][HR_DATA] <= HR_AMBER[HIGH])):
                    self.colorText("yellow")
                elif((sensorData[i][VITALS_DATA][HR_DATA] >= HR_RED[LOW] and sensorData[i][VITALS_DATA][HR_DATA] < HR_AMBER[LOW]) or \
                    (sensorData[i][VITALS_DATA][HR_DATA] > HR_AMBER[HIGH] and sensorData[i][VITALS_DATA][HR_DATA] <= HR_RED[HIGH])):
                    self.colorText("red")
                elif(sensorData[i][VITALS_DATA][HR_DATA] <= HR_BLACK[LOW] or sensorData[i][VITALS_DATA][HR_DATA] >= HR_BLACK[HIGH]):
                    self.colorText("blue")

                # Print Data
                print_at(HR_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][VITALS_DATA][HR_DATA]) + "   ")

            #< SPO2 >#
            for i in range(WARRIOR_TOTAL):
                # Determine Color Status
                if(sensorData[i][VITALS_DATA][SPO2_DATA] > SPO2_AMBER and sensorData[i][VITALS_DATA][SPO2_DATA] <= SPO2_GREEN):
                    self.colorText("green")
                elif(sensorData[i][VITALS_DATA][SPO2_DATA] > SPO2_RED and sensorData[i][VITALS_DATA][SPO2_DATA] <= SPO2_AMBER):
                    self.colorText("yellow")
                elif(sensorData[i][VITALS_DATA][SPO2_DATA] > SPO2_BLACK and sensorData[i][VITALS_DATA][SPO2_DATA] <= SPO2_RED):
                    self.colorText("red")
                elif(sensorData[i][VITALS_DATA][SPO2_DATA] <= SPO2_BLACK):
                    self.colorText("blue")

                # Print Data
                print_at(SPO2_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][VITALS_DATA][SPO2_DATA]) + "   ")

            #< RESP >#
            for i in range(WARRIOR_TOTAL):
                # Determine Color Status
                if(sensorData[i][VITALS_DATA][RESP_DATA] >= RESP_GREEN[LOW] and sensorData[i][VITALS_DATA][RESP_DATA] <= RESP_GREEN[HIGH]):
                    self.colorText("green")
                elif((sensorData[i][VITALS_DATA][RESP_DATA] >= RESP_AMBER[LOW] and sensorData[i][VITALS_DATA][RESP_DATA] < RESP_GREEN[LOW]) or \
                    (sensorData[i][VITALS_DATA][RESP_DATA] > RESP_GREEN[HIGH] and sensorData[i][VITALS_DATA][RESP_DATA] <= RESP_AMBER[HIGH])):
                    self.colorText("yellow")
                elif((sensorData[i][VITALS_DATA][RESP_DATA] >= RESP_RED[LOW] and sensorData[i][VITALS_DATA][RESP_DATA] < RESP_AMBER[LOW]) or \
                    (sensorData[i][VITALS_DATA][RESP_DATA] > RESP_AMBER[HIGH] and sensorData[i][VITALS_DATA][RESP_DATA] <= RESP_RED[HIGH])):
                    self.colorText("red")
                elif(sensorData[i][VITALS_DATA][RESP_DATA] <= RESP_BLACK[LOW] or sensorData[i][VITALS_DATA][RESP_DATA] >= RESP_BLACK[HIGH]):
                    self.colorText("blue")

                # Print Data
                print_at(RESP_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][VITALS_DATA][RESP_DATA]) + "   ")

            #< TEMP >#
            for i in range(WARRIOR_TOTAL):
                # Determine Color Status
                if(sensorData[i][VITALS_DATA][TEMP_DATA] >= TEMP_GREEN[LOW] and sensorData[i][VITALS_DATA][TEMP_DATA] <= TEMP_GREEN[HIGH]):
                    self.colorText("green")
                elif((sensorData[i][VITALS_DATA][TEMP_DATA] >= TEMP_AMBER[LOW] and sensorData[i][VITALS_DATA][TEMP_DATA] < TEMP_GREEN[LOW]) or \
                    (sensorData[i][VITALS_DATA][TEMP_DATA] > TEMP_GREEN[HIGH] and sensorData[i][VITALS_DATA][TEMP_DATA] <= TEMP_AMBER[HIGH])):
                    self.colorText("yellow")
                elif((sensorData[i][VITALS_DATA][TEMP_DATA] >= TEMP_RED[LOW] and sensorData[i][VITALS_DATA][TEMP_DATA] < TEMP_AMBER[LOW]) or \
                    (sensorData[i][VITALS_DATA][TEMP_DATA] > TEMP_AMBER[HIGH] and sensorData[i][VITALS_DATA][TEMP_DATA] <= TEMP_RED[HIGH])):
                    self.colorText("red")
                elif(sensorData[i][VITALS_DATA][TEMP_DATA] <= TEMP_BLACK[LOW] or sensorData[i][VITALS_DATA][TEMP_DATA] >= TEMP_BLACK[HIGH]):
                    self.colorText("blue")

                # Print Data
                print_at(TEMP_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][VITALS_DATA][TEMP_DATA]) + "   ")

            #< WEAPON >#
            for i in range(WARRIOR_TOTAL):
                if(sensorData[i][WEAPON_DATA] == WEAPON_GREEN):
                    self.colorText("green")
                elif(sensorData[i][WEAPON_DATA] == WEAPON_AMBER):
                    self.colorText("yellow")
                elif(sensorData[i][WEAPON_DATA] > WEAPON_RED):
                    self.colorText("red")
                elif(sensorData[i][WEAPON_DATA] >= WEAPON_BLACK[LOW] or sensorData[i][WEAPON_DATA] <= WEAPON_BLACK[HIGH]):
                    self.colorText("blue")

                # Print Data
                print_at(WEAPON_ROW, DATA_START + (DATA_SPACING * i), str(sensorData[i][WEAPON_DATA]) + "   ")

    def colorText(self, color):
        # lock the colorText if it is in use by another process
        while(self.colorText_Mutex.value == 1):
            pass

        # lock mutex
        self.colorText_Mutex.value = 1
        if(color == "red"):
            print(chr(27) + "[31m" + chr(27) + "[033F")
        elif(color == "green"):
            print(chr(27) + "[32m" + chr(27) + "[033F")
        elif(color == "yellow"):
            print(chr(27) + "[33m" + chr(27) + "[033F")
        elif(color == "blue"):
            print(chr(27) + "[34m" + chr(27) + "[033F")
        elif(color == "magenta"):
            print(chr(27) + "[35m" + chr(27) + "[033F")
        elif(color == "cyan"):
            print(chr(27) + "[36m" + chr(27) + "[033F")
        elif(color == "white"):
            print(chr(27) + "[37m" + chr(27) + "[033F")

        #unlock mutex
        self.colorText_Mutex.value = 0

    def hideCursor(self):
        print("\033[?25h")

class ConnectionStatus(object):

    def __init__(self):
        self.stateIndicatorTable = ["|", "/", "-", "\\"]
        self.errorIndicator = "0"
        self.errorState = 0
        self.stateIndicator = 0

    """ Cyclic Incrementing """
    def incrementStateIndicator(self):
        if(self.stateIndicator < len(self.stateIndicatorTable) - 1):
            self.stateIndicator += 1

        else:
            self.stateIndicator = 0

    def getStateIndicator(self):
        return self.stateIndicatorTable[self.stateIndicator]

    def displayConnectionStatus(self):
        while(1):
            time.sleep(1)
            if(not self.errorState):
                print_at(CONNECTION_STATUS_ROW, CONNECTION_STATUS_START, str(self.getStateIndicator()))
            else:
                print_at(CONNECTION_STATUS_ROW, CONNECTION_STATUS_START, str(self.errorIndicator))

# Depricated, but still might be useful
if(RUNMODE is DEMO):
    # Setup
    connectionStatus = ConnectionStatus()
    messagePrintService = MessagePrintService()

    clearScreen()
    messagePrintService.displayStructure()

    counter = 0

    # Loop
    while(1):
        #messagePrintService.displayData() #< to run this, pass in sample data
        if(not(counter % 200)):
            connectionStatus.incrementStateIndicator()
            counter += 1

        elif(counter is 1000):
            clearScreen()
            messagePrintService.displayStructure()
            counter = 0

        else:
            counter += 1

        connectionStatus.displayConnectionStatus()


import torch
import torch.nn as nn

class CNN3D(nn.Module):
    """Base 3D convolutional neural network architecture for molecular data, consisting of six layers of 3D convolutions, each followed by batch normalization, ReLU activation, and optionally dropout.
    This network uses strided convolutions to downsample the input twice by half, so the original box size must be divisible by 4 (e.g. an atomic environment of side length 20 Å with 1 Å voxels). The final convolution reduces the 3D box to a single 1D vector of length ``out_dim``.
    The desired input and output dimensionality must be specified when instantiating the model.

    :param in_dim: Input dimension.
    :type in_dim: int
    :param out_dim: Output dimension.
    :type out_dim: int
    :param box_size: Size (edge length) of voxelized 3D cube.
    :type box_size: int
    :param hidden_dim: Base number of hidden units, defaults to 64
    :type hidden_dim: int, optional
    :param dropout: Dropout probability, defaults to 0.1
    :type dropout: float, optional
    """
    def __init__(self, in_dim, out_dim, box_size, hidden_dim=64, dropout=0.1):
        super(CNN3D, self).__init__()
        self.out_dim = out_dim

        self.model = nn.Sequential(
            nn.Conv3d(in_dim, hidden_dim, 4, 2, 1, bias=False),
            nn.BatchNorm3d(hidden_dim),
            nn.ReLU(inplace=True),
            nn.Dropout(dropout),

            nn.Conv3d(hidden_dim, hidden_dim * 2, 3, 1, 1, bias=False),
            nn.BatchNorm3d(hidden_dim * 2),
            nn.ReLU(inplace=True),
            nn.Dropout(dropout),

            nn.Conv3d(hidden_dim * 2, hidden_dim * 4, 4, 2, 1, bias=False),
            nn.BatchNorm3d(hidden_dim * 4),
            nn.ReLU(inplace=True),
            nn.Dropout(dropout),

            nn.Conv3d(hidden_dim * 4, hidden_dim * 8, 3, 1, 1, bias=False),
            nn.BatchNorm3d(hidden_dim * 8),
            nn.ReLU(inplace=True),
            nn.Dropout(dropout),

            nn.Conv3d(hidden_dim * 8, hidden_dim * 16, 3, 1, 1, bias=False),
            nn.BatchNorm3d(hidden_dim * 16),
            nn.ReLU(inplace=True),
            nn.Dropout(dropout),

            nn.Conv3d(hidden_dim * 16, out_dim, box_size / 4, 1, 0, bias=False),
        )

    def forward(self, input):
        """Forward method.

        :param input: Input data, as voxelized 3D cube of shape (batch_size, in_dim, box_size, box_size, box_size).
        :type input: torch.FloatTensor
        :return: Output of network, of shape (batch_size, out_dim)
        :rtype: torch.FloatTensor
        """
        bs = input.size()[0]

        output = self.model(input)
        return output.view(bs, self.out_dim)


# ## Proyecto final de optimización 1
# ### Max K cut par k=2 usando semi definite relaxation

# # Parte 1: Importar el conjunto de grafos que se van a probar

import networkx as nx
import numpy as np

def cargar_grafos(path):
    graph = nx.Graph()
    with open(path) as file:
        n_nodes = int(file.readline().split(' ', 1)[0])
        graph.add_nodes_from(range(n_nodes))
        for row in file:
            start, end, weight = [int(e) for e in row.strip('\n').split()]
            graph.add_edge(start - 1, end - 1, weight=weight)
    '''graph.add_nodes_from([1, 2, 3, 4])
    graph.add_weighted_edges_from([(1, 2, 1), (2, 3, 4), (1, 4, 3), (3, 4, 2)])'''
    return graph

# ## Parte 2: Creación de la clase abstracta para la solución de máximo corte

#creación de la clase para resolver el problema de la SDP
#Una clase abstracta importada de la librería abc
import cvxpy as cp
from abc import ABCMeta, abstractmethod

# In[50]:

class AbstractMaxCut(metaclass=ABCMeta):
    def __init__(self,graph):
        self.graph=graph
        self._solution=None

    def get_results(self, item='cut', verbose=False): #Regresa los lazy evaluated max-cut alcanzados, regresa el corte o su valor en la matriz inicial resolviendo el programa SDP
        if self._results is None:
            self.solve(verbose)
        if item not in self._results:
            valid = ', '.join(["'%s'" % key for key in self._results.keys()])
            raise KeyError(
                "In valid 'item' keyword: should be one of {{%s}}." % valid
            )
        return self._results.get(item)

    @abstractmethod
    def solve(self, verbose=True):
        #Resolver el problema BM formulado del max cut usando RTR
        return NotImplemented

def get_partition(vectors):
	#Usa el redondeo Goemans-Williamson
    random = np.random.normal(size=vectors.shape[1])
    random /= np.linalg.norm(random, 2)
    # Calcula las probabilidades de partición y redondea el resultado
    return np.sign(np.dot(vectors, random))

def get_cut_value(graph, partition):
    # Regresa el costo de la partición del grafo
    in_cut = sum(attr['weight'] for u, v, attr in graph.edges(data=True) if partition[u] != partition[v])
    total = .5 * nx.adjacency_matrix(graph).sum()
    return in_cut / total

class MaxCutSDP(AbstractMaxCut):
    """Solver Semi-Definite Programming para la solución del Max-Cut Problem, el resultado final es un conjunto de {+1,-1} que indica la pertenencia al grafo """

    def __init__(self, graph, solver='scs'):
        super().__init__(graph)
        solver = solver.upper()
        if solver not in cp.installed_solvers():
            raise KeyError("Solver '%s' no instalado." % solver)
        self.solver = getattr(cp, solver)

    def solve(self, verbose=True):
        matrix = self._solve_sdp()
        matrix = nearest_psd(matrix)
        # Tenemos el corte definido por la matriz
        vectors = np.linalg.cholesky(matrix)
        cut = get_partition(vectors)
        # Tenemos el valor del crte
        value = get_cut_value(self.graph, cut)
        self._results = {'matrix': matrix, 'cut': cut, 'value': value}
        # Optionally be verbose about the results.
        if verbose:
            print(
                "Problema SDP-relaxed max-cut resuelto.\n"
                "Cortes solución de %f Comparten un peso total." % value
            )
            print(self._results['cut'])
            print(self._results['matrix'])

    def _solve_sdp(self):
        """Resuelve el problema SDP del maximo corte.
        regresa la matriz que maximiza <C, 1 - X>
        """
        # Gather properties of the graph to cut.
        n_nodes = len(self.graph)
        adjacent = nx.adjacency_matrix(self.graph).toarray() #Convertir la matriz de adyacencia a los
        matrix = cp.Variable((n_nodes, n_nodes), PSD=True)
        cut = .25 * cp.sum(cp.multiply(adjacent, 1 - matrix))
        problem = cp.Problem(cp.Maximize(cut), [cp.diag(matrix) == 1])
        # resolver el programa
        problem.solve(getattr(cp, self.solver))
        return matrix.value

def nearest_psd(matrix):
	#la matriz regresa la matriz positiva definida más cercana a la matriz original, se checa que sea semipositiva definida si no se crea una matriz semi positiva definida
    if is_psd(matrix):
        return matrix
    spacing = np.spacing(np.linalg.norm(matrix))
    identity = np.identity(len(matrix))
    k = 1
    while not is_psd(matrix):
        min_eig = np.min(np.real(np.linalg.eigvals(matrix)))
        matrix += identity * (- min_eig * (k ** 2) + spacing)
        k += 1
    return matrix

def is_psd(matrix):
    #Checamos si una matriz es semi definida positiva con la factorización de Cholesky
    try:
        _ = np.linalg.cholesky(matrix)
        return True
    except np.linalg.LinAlgError:
        return False

# ## Parte de la prueba del algoritmo de Max Cut

import random

random.seed(0)
n = 100
p = 0.8
file = "G1"
MAX = 10000
vec = []
edges = []
set = set()
for i in range(n):
    for j in range(n):
        if i == j:
            continue
        if (j, i) in edges:
            print(0)
            continue
        if random.randint(1, MAX)/MAX < p:
            continue
        edges.append((i, j))
        vec.append((i+1, j+1, random.randint(1, 100)))
        set.add(i)
        set.add(j)
with open(file, "w") as f:
    f.write('{} {}'.format(len(set), len(vec)))
    f.write('\n')
    for i in vec:
        f.write('{} {} {}'.format(*i))
        f.write('\n')
    f.close()

grafo=cargar_grafos(file)
print(type(grafo))

import matplotlib.pyplot as plt
nx.draw(grafo, with_labels=True)  # networkx draw()
plt.draw()
plt.savefig("G.png")

# In[53]:

sdp = MaxCutSDP(grafo)
print("Solver")
sdp.solve(grafo)

cut = sdp.get_results('cut')
print(cut)

A = [i for i in range(len(cut)) if cut[i] == 1]
B = [i for i in range(len(cut)) if cut[i] == -1]
print(A, B)

colors = []
edges = grafo.edges()
for u, v in edges:
    if (u in A) and (v in A):
        colors.append('blue')
        continue
    if (u in B) and (v in B):
        colors.append('green')
        continue
    #colors.append('red')
    grafo.remove_edge(u, v)

print(colors)

plt.figure()
nx.draw(grafo, with_labels=True, edge_color=colors)  # networkx draw()
plt.draw()
plt.savefig("G_cut.png")

for i in range(1, n):
    for j in range(1, n):
        pass


import os

import torch
import torch.nn as nn
import numpy as np
import time
from utils.utils_attacks import test_madry, madry_train_one_epoch
from utils.utils_trades import trades_train_one_epoch
from utils.utils_pruning import get_init_masks
from utils.utils_training import train_one_epoch, train_one_epoch_l1, test
from utils.utils_mixtrain import test_vra, mixtrain_parallel_one_epoch
from utils.utils_IBP import test_ibp_vra, ibp_one_epoch
from utils.utils_noise import train_one_noise_epoch, test_noise
from utils.utils import Logger, load_cifar_dataset, set_seed

from models import cifar_model_large, vgg, vgg_no_bn, cifar_model_small, cifar_conv2, cifar_conv4, cifar_conv4_bn_max2
from wideresnet import WideResNet
from resnet import ResNet18

import argparse
from config import argparse_config
import random
import sys
import math
def load_model(net, model_path):
    print("model loading from " + model_path)
    net.load_state_dict(torch.load(model_path))
    if torch.cuda.is_available:
        net = net.cuda()

def load_model_type(args):
    '''
    assert args.model_type in["vgg16", "large", "small", "conv2", "wideresnet",\
                        "wideresnet_28_10", "wideresnet_28_5", "resnet18", "vgg11",
                        "vgg8s", "vgg8", "vgg7", "conv2_4", "conv2_16", "conv4", "conv4_2",
                        "vgg8_no_bn", "conv4_bn_max2"]
    '''

    if args.model_type == "vgg16":
        m = vgg(dataset=args.dataset)
    elif args.model_type == "vgg11":
        m = vgg(depth=11)
    elif args.model_type == "vgg8s":
        m = vgg(depth='8s')
    elif args.model_type == "vgg8":
        m = vgg(depth=8)
    elif args.model_type == "vgg7":
        m = vgg(depth=7)
    elif args.model_type == "vgg7_avg4":
        m = vgg(depth=7)
    elif args.model_type == "vgg8_no_bn":
        m = vgg_no_bn(depth=8)
    elif args.model_type == "conv2":
        m = cifar_conv2()
    elif args.model_type == "conv2_4":
        m = cifar_conv2(depth=4)
    elif args.model_type == "conv2_16":
        m = cifar_conv2(depth=16)
    elif args.model_type == "conv4":
        m = cifar_conv4(depth=1)
    elif args.model_type == "conv4_bn_max2":
        m = cifar_conv4_bn_max2(depth=1)
    elif args.model_type == "conv4_2":
        m = cifar_conv4(depth=2)
    elif args.model_type == "large":
        m = cifar_model_large(width=args.model_width)
        args.model_type = args.model_type + "_w" + str(args.model_width)
    elif args.model_type == "small":
        m = cifar_model_small(width=args.model_width)
        args.model_type = args.model_type + "_w" + str(args.model_width)

    elif args.model_type == "wideresnet":
        m = WideResNet()
    elif args.model_type == "wideresnet_34_8":
        m = WideResNet(depth=34, widen_factor=8)
    elif args.model_type == "wideresnet_34_5":
        m = WideResNet(depth=34, widen_factor=5)
    elif args.model_type == "wideresnet_34_2":
        m = WideResNet(depth=34, widen_factor=2)
    elif args.model_type == "wideresnet_34_1":
        m = WideResNet(depth=34, widen_factor=1)

    elif args.model_type == "wideresnet_28_10":
        m = WideResNet(depth=28, widen_factor=10)
    elif args.model_type == "wideresnet_22_10":
        m = WideResNet(depth=22, widen_factor=10)
    elif args.model_type == "wideresnet_16_10":
        m = WideResNet(depth=16, widen_factor=10)
    elif args.model_type == "wideresnet_10_10":
        m = WideResNet(depth=10, widen_factor=10)

    elif args.model_type == "resnet18":
        m = ResNet18()

    else:
        print("no such model type")

    if torch.cuda.is_available:
        m.model = m.model.cuda()

    return m

class early_stop_evaluation():
    def __init__(self, max_size=10):
        self.loss_valid_queue = [100000]
        self.max_size = max_size
        self.save = False

    def check_early_stop(self, loss_valid):
        if loss_valid >= self.loss_valid_queue[0] - 1e-5:
            self.save = False
            self.loss_valid_queue.append(loss_valid)
            if len(self.loss_valid_queue) == self.max_size:
                return True
        else:
            self.loss_valid_queue = [loss_valid]
            self.save = True
            return False

    def check_save_best(self):
        if self.save:
            return True
        else:
            return False

def train_model(m, mask, loader_train, loader_valid, loader_test, args, train_type, verbose=False):

    net = m.model.cuda()

    criterion = nn.CrossEntropyLoss()
    if args.optm == "sgd":
        optimizer = torch.optim.SGD(net.parameters(),
                                    lr=args.learning_rate,
                                    momentum=0.9,
                                    weight_decay=args.weight_decay)
    elif args.optm == "adam":
        optimizer = torch.optim.Adam(net.parameters(), lr=args.learning_rate)

    else:
        print("no such optimizer!")

    early_check = early_stop_evaluation(max_size=args.early_stop)

    best_acc = -1
    acc = -1
    best_pgd_acc = -1
    pgd_acc = -1
    best_vra = -1
    vra = -1
    start_time = time.time()

    for t in range(args.resume, args.train_epochs):
        current_time = time.time()-start_time
        if t==args.resume:
            print("Epoch [%d/%d]"%(t, args.train_epochs))
        else:
            print("Epoch [%d/%d], Passed time:[%.3f/%.3f]"%(t, args.train_epochs,\
                        (current_time)/(t-args.resume), current_time))
        #optimizer.param_groups[0]["lr"] = set_lr(args, t)
        set_lr(args, t, optimizer)
        print("learning rate:", optimizer.param_groups[0]["lr"])

        '''
        # if args.is_training: train_type is args.train_method
        # else: train_type is args.finetune_method
        # therefore we have to saperate it
        '''
        if train_type == "nat":
            train_one_epoch(m, mask, criterion, optimizer, loader_train, args, verbose=args.verbose)
            print("Valid Test with nat")
            acc, ce = test(net, loader_valid, criterion)

            if args.early_stop > 0:
                if early_check.check_early_stop(ce):
                    print("Early stop at ", early_check.loss_valid_queue, "best model loaded from", args.model_path)
                    load_model(net, args.model_path)
                    print("Test with test set:")
                    best_acc, best_ce = test(net, loader_test, criterion)
                    return best_acc, best_pgd_acc

        elif train_type == "nat_l1":
            train_one_epoch_l1(m, mask, criterion, optimizer, loader_train, args, verbose=args.verbose)
            print("Valid Test with nat")
            acc, ce = test(net, loader_valid, criterion)

            if args.early_stop > 0:
                if early_check.check_early_stop(ce):
                    print("Early stop at ", early_check.loss_valid_queue, "best model loaded from", args.model_path)
                    load_model(net, args.model_path)
                    print("Test with test set:")
                    best_acc, best_ce = test(net, loader_test, criterion)
                    return best_acc, best_pgd_acc

        elif train_type == "madry":
            args.eps_step = 2./255.
            args.attack_iter = 10
            print("Train with PGD")
            madry_train_one_epoch(m, mask, criterion, optimizer, loader_train, args, verbose=args.verbose)
            print("Valid Test with PGD")
            acc, pgd_acc = test_madry(net, loader_valid, args)

        elif train_type == "trades":
            args.eps_step = 2./255.
            args.attack_iter = 10
            print("Train with Trades")
            trades_train_one_epoch(m, mask, optimizer, loader_train, args, verbose=args.verbose)
            print("Valid Test with PGD")
            acc, pgd_acc = test_madry(net, loader_valid, args)

            if pgd_acc > best_pgd_acc:
                best_pgd_acc = pgd_acc
                torch.save(m.model.state_dict(), args.model_path)
                print("best model saved to ", args.model_path, "with acc", acc, "and pgd_acc", pgd_acc)

        elif train_type == "trades_fgsm":
            args.eps_step = 8./255.
            args.attack_iter = 1
            print("Train with Trades FGSM")
            trades_train_one_epoch(m, mask, optimizer, loader_train, args, verbose=args.verbose)

            args.eps_step = 2./255.
            args.attack_iter = 10
            if t % 10 == 9:
                print("Valid Test with PGD")
                acc, pgd_acc = test_madry(net, loader_valid, args)
                args.eps_step = 8./255.
                args.attack_iter = 1

        elif train_type == "fgsm":
            args.eps_step = 8./255.
            args.attack_iter = 1
            print("Train with FGSM")
            madry_train_one_epoch(m, mask, criterion, optimizer, loader_train, args, verbose=args.verbose)
            if t % 20 == 19:
                print("Valid Test with FGSM")
                acc, pgd_acc = test_madry(net, loader_valid, args)

                args.eps_step = 2./255.
                args.attack_iter = 10
                print("Test with PGD")
                acc, pgd_acc = test_madry(net, loader_valid, args)
                args.eps_step = 8./255.
                args.attack_iter = 1

        elif train_type == "mixtrain":
            mixtrain_parallel_one_epoch(loader_train, m, mask, optimizer,
                    args.epsilon, interval_weight=args.ft_interval_weight, verbose=args.verbose,
                    bounded_input=False, clip_grad=1)

        elif train_type == "naive":
            print(t, args.schedule_length, min(float(t)/float(args.schedule_length), 1.))
            epsilon = args.epsilon * min(float(t)/float(args.schedule_length), 1.)
            ibp_one_epoch(loader_train, m, mask, optimizer,
                    epsilon, interval_weight=args.ft_interval_weight, verbose=args.verbose,
                    clip_grad=1)
            print("Valid Test with naive")
            vra = test_ibp_vra(m.model, loader_valid, args)
        elif train_type == 'noise':
            train_one_noise_epoch(m, mask, criterion, args.noise_sd, optimizer, loader_train, verbose=args.verbose)
            print("Valid Test with noise")
            acc = test_noise(net, args.noise_sd, loader_valid)
        else:
            print("no such traininig method!")
            exit()

        if early_check.check_save_best() and not args.create_init:

            #torch.save(net.state_dict(), args.model_path)
            print("Best model so far saved in", args.model_path)
            print("Test on test set:")
            if train_type in ["nat", "nat_l1"]:
                best_acc, best_ce = test(net, loader_test, criterion)
            else:
                acc, pgd_acc = test_madry(net, loader_test, args)

    #torch.save(net.state_dict(), args.model_path)
    print("Training done, model saved in", args.model_path)
    print("Test on test set:")
    if train_type == "nat":
        best_acc, best_ce = test(net, loader_test, criterion)
    else:
        acc, pgd_acc = test_madry(net, loader_test, args)

    return best_acc, best_pgd_acc

def set_lr(args, t, optimizer):
    if args.warmup:
        for param_group in optimizer.param_groups:
            if args.model_type == "vgg16":
                if t<10:
                    # no warmup for finding mask should be 0.01
                    # warmup for enhancement should be from 0.01 to 0.1
                    param_group['lr'] = 0.1*(t+1)*args.learning_rate
            elif args.model_type == "resnet18":
                if t<11:
                    # warmup for finding mask should be from 0.01 to 0.1(best)/0.005 to 0.05
                    # no warmup for finding mask should be 0.05 compare to 0.1
                    # warmup for enhancement should be from 0.05 to 0.1
                    param_group['lr'] = t*(args.learning_rate - 0.05)/10. + 0.05
            elif "wideresnet" in args.model_type:
                if t<11:
                    # warmup for finding mask should be from 0.01 to 0.1(best)/0.005 to 0.05
                    # no warmup for finding mask should be 0.05 compare to 0.1
                    # warmup for enhancement should be from 0.05 to 0.1
                    #param_group['lr'] = 0.1*(t+1)*args.learning_rate
                    param_group['lr'] = t*(args.learning_rate - 0.05)/10. + 0.05

    if t in [math.ceil(args.train_epochs*0.5), math.ceil(args.train_epochs*0.75)]:
        for param_group in optimizer.param_groups:
            param_group['lr'] *= 0.1
    '''
    for param_group in optimizer.param_groups:
        param_group['lr'] = args.learning_rate * (0.6 ** ((max((t-args.schedule_length), 0) // 5)))
    '''

def path_config(args):
    args.model_path = os.path.join(args.model_path + args.dataset + "/")
    path = os.path.join(args.model_path + args.model_type + "/")

    if args.model_name is None:
        args.model_name = "train"
        if args.train_method == "noise":
            args.model_name = "train_sd"+str(args.noise_sd)
        if args.train_method == "trades":
            args.model_name = "train_beta"+str(args.trades_beta)

    if not args.norm:
        args.model_name = args.model_name + "_nn"

    path = os.path.join(path + "training/" + args.train_method + "/")

    if not os.path.exists(path):
        os.makedirs(path)
        print("making dir:", path)
    args.model_path = os.path.join(path + args.model_name + ".pth")
    args.log_path = os.path.join(path + args.model_name + ".log")
    return args

# python train.py vgg16 pure
# --train_method nat (train method)
# --gpu 0 (=0)
# --learning_rate (=0.01, the lr used for enhancement)
# --train_epochs (=train_epochs, the epoch used for enhancement)
# --model_name (=default, will save to model_name.log/pth)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    args = argparse_config(parser)

    os.environ['CUDA_DEVICE_ORDER'] = 'PCI_BUS_ID'
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu

    if args.seed is None:
        args.seed = 7

    set_seed(args.seed)

    loader_train, loader_valid, loader_test = load_cifar_dataset(args, data_dir='./data')

    assert args.train_method in ["nat", "madry", "mixtrain", "fgsm",\
                        "naive", "sym", "noise", "trades", "trades_fgsm"],\
                        "no such train method!"
    assert args.init_type in ["nat", "madry", "pure", "trades"]
    assert args.init_step > 0, "please use init_type=pure if init_step is 0"

    m = load_model_type(args)
    net = m.model

    args = path_config(args)

    if args.log_path is not None:
        log = open(args.log_path, "w")
        sys.stdout = Logger(log)

    if torch.cuda.is_available():
        print('CUDA enabled.')
        net = net.cuda()

    for k in args.__dict__:
        print(k, ":", args.__dict__[k])

    print("config:")
    print("training method:", args.train_method)
    print("model will be saved in:", args.model_path)
    print("Log will be saved in", args.log_path)
    if args.resume !=0:
        print("Resume from epoch", args.resume)
        log = open(args.log_path, "a")
        sys.stdout = Logger(log)
        load_model(m.model, args.model_path)
        print("model resumed from", args.model_path)

    # Just regular training with args.train_method
    if args.parallel:
        print("Model parallel!")
        m.model = nn.DataParallel(m.model).cuda()
    train_model(m, get_init_masks(net), loader_train, loader_valid, loader_test,\
            args, train_type=args.train_method, verbose=False)
    exit()


from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
admin.autodiscover()

from .views import *

urlpatterns = patterns('',
    # Examples:
    url(r'^get_containers$',    get_containers),
    url(r'^get_container$',    get_container),
    # url(r'^create_container$',  create_container),
    url(r'^auto_create_container$',  auto_create_container),
    url(r'^reset_end_date$', reset_end_date),
    # url(r'^get_ipv4pool$',      get_ipv4pool),
    # url(r'^blog/', include('blog.urls')),

   # url(r'^network', 'network'),

   url(r'^get_token$',      get_token),
    )

urlpatterns += patterns('api.tests',
    url(r'^create_container_test$', 'create_container_test'),
)


from numpy import *

n = int(input('Enter n(3, 5, 7...): '))

row = 0
col = n // 2
magic = zeros((n, n))
magic[row][col] = 1

for num in range(2, n*n + 1):
    row_new = (row - 1 + n) % n
    col_new = (col + 1) % n

    if magic[row_new][col_new] == 0:
        row = row_new
        col = col_new
    else:
        row = (row + 1) % n

    magic[row][col] = num

print()
print(magic)


#!/usr/bin/env python
from __future__ import print_function, division

try:
    import httk
except Exception:
    import sys, os.path, inspect
    _realpath = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0]))
    sys.path.insert(1, os.path.join(_realpath, '../..'))
    import httk

import httk.atomistic.vis
from httk.atomistic import Structure

### Example 1

struct = Structure.io.load("POSCAR")
print(struct)
struct.vis.show({'bonds': True, 'extbonds': False, 'polyhedra': False})
struct.vis.wait()

symstruct = struct.find_symmetry()

symstruct.vis.show({'bonds': True, 'extbonds': False, 'polyhedra': False})
# This below allows you to see the primitive cell
#struct.vis.show({'bonds':True, 'extbonds':False, 'polyhedra':False, 'unitcell':struct.uc_cell.basis, 'show_supercell':True})
symstruct.vis.wait()

### Example 2

struct = Structure.io.load("POSCAR2")

struct.vis.show(debug=True)
struct.vis.wait()

struct = struct.pc.supercell.orthogonal(tolerance=15)
struct.vis.show()
struct.vis.wait()

struct = struct.pc.supercell.cubic(tolerance=15)
struct.vis.show({'extbonds': False})
struct.vis.wait()


import sys
# pyqt5
from PyQt5.QtCore import QRect, QThread, QMutex, QTimer
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QLabel, QTextEdit, QVBoxLayout, QHBoxLayout, QLCDNumber, \
    QLineEdit
from mainWindow import OSUi, InnerCmd,Handler

# 窗口大小设置
UI_SIZE = QRect(400, 400, 800, 1000)

if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow

    # import pics_ui_rc  # 导入添加的资源（根据实际情况填写文件名）
    app = QApplication(sys.argv)

    # 开启线程
    handler = Handler()
    handler.start()

    elevators = []
    for i in range(5):
        elevators.append(InnerCmd(i))

    for elevator in elevators:
        print(elevator.eId)
        elevator.start()

    ui = OSUi()
    sys.exit(app.exec_())