from random import choice, randint
import time
from threading import Thread 	# for ingame day cycle.

import os
from termcolor import cprint, colored	# colored output on screen

from string import printable	# for attribute point spend checking.

import pickle 	# for saving and loading profiles.
import os 		# for saving and loading profiles.

import sys 		# sys.exit()

os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"	# do not print message on pygame import
from pygame import mixer	# background music

os.system("color")		# colored output can be used now
mixer.init()			# initialize for later usage

def clear_screen():
	os.system("cls" if os.name=="nt" else "clear")

###
### Configuration
###
class Config():
	def __init__(self):
		self.ATTR_POINTS_HILVL = 6		# attribute points gained at levelup after level 5
		self.ATTR_POINTS_INITIAL = 10	# attribute points given in the beginning
		self.ATTR_POINTS_LOWLVL = 3		# attribute points gained at levelup before level 5
		self.BRAVERY_CRITDMG = 0.1		# bravery's increase rate of critmultiplier
		self.BRAVERY_FLEEDELAY = 3
		self.DEBUGMDOE = False
		self.DEFENSE_ABSORB = 7/8
		self.DEFENSE_CURRHP_INCREASE = 1
		self.ENEMY_INITIAL_DMG = 3
		self.ENEMY_INITIAL_HP = 1
		self.ENEMY_INITIAL_DEF = 1
		self.ENEMY_INITIAL_SPD = 1
		self.ENEMY_INITIAL_LCK = 1
		self.ENEMY_INITIAL_RGN = 0
		self.ENEMY_MAX_LEVEL = 2
		self.ENEMY_MIN_LEVEL = -2
		self.HP_CURRHP_INCREASE = 10
		self.INCORRECT_STAT_ENTRY_HI = printable.translate({ord(i): None for i in "1234567"})
		self.INCORRECT_STAT_ENTRY_LO = printable.translate({ord(i): None for i in "123"})
		self.MUSIC_BATTLE = "music/RH_test_battle.mp3"
		self.MUSIC_ENEMYENCOUNTER = ""
		self.MUSIC_LEVELUP = "music/RH_test_levelup.mp3"
		self.MUSIC_LOOTENCOUNTER = "music/RH_test_lootencounter.mp3"
		self.MUSIC_MAIN = "music/RH_test_main.mp3"
		self.QUICK_TURN = 20
		self.REGEN_MULTIPLIER = 2/4
		self.TURNLIMIT_MAX = 20
		self.TURNLIMIT_XPHI = 6
		self.TURNLIMIT_XPLOW = 3
		self.XP_TO_NEXTLEVEL = 100

cfg = Config()

class Clock():
	def __init__(self):
		self.clock_thread = Thread(target=self.start)
		self.clock_thread.daemon = True
	def start(self):
		self.clock_thread.start()
	def stop(self):
		pass

###
### Hero Class
###

###		attributes:
#	damage		-> amount of harm applied to enemy
#	hp			-> maximum amount of damage player can withstand
#	defense		-> decrase damage taken
#	speed		-> increase turn frequency and dodge rate
#	bravery		-> delay enemy flee and increase critmultiplier
#	luck 		-> increase crit chance and enemy loot
#	regeneration-> hp increase rate
#
#	xp			-> required to level up
#	level 		-> player level
#
#	weapon 		-> affects min-max damage and speed
#
class RandomHero():
	def __init__(self, name, damage, hp, defense, speed=1, bravery=0, luck=5, regeneration=1, xp=0, level=1, weapon=None, critmultiplier=1.2, color="green", money=0):
		self.all_attr = dict()
		self.name = name
		self.damage = damage
		self.defense = defense
		self.hp = hp
		self.max_hp = self.hp*10 + self.defense
		self.curr_hp = self.max_hp
		self.bravery = bravery
		self.luck = luck
		self.regeneration = regeneration
		self.xp = xp
		self.level = level
		if not weapon:
			self.weapon = Weapon("Fist", -1, 1, 0)
		else:
			self.weapon = weapon
		self.mindmg = self.weapon.mindmg + damage
		self.maxdmg = self.weapon.maxdmg + damage
		self.speed = speed + self.weapon.speed
		self.critmultiplier = critmultiplier + self.damage/20 + self.bravery*cfg.BRAVERY_CRITDMG
		self.updateAttrdict()
		self.color = color
		self.money = money

	def __str__(self):
		return str(sorted(self.updateAttrdict().items()))

	def updateAttrdict(self):
		self.all_attr["name"] = self.name
		self.all_attr["damage"] = self.damage
		self.all_attr["hp"] = self.hp
		self.all_attr["defense"] = self.defense
		self.all_attr["speed"] = self.speed
		self.all_attr["bravery"] = self.bravery
		self.all_attr["luck"] = self.luck
		self.all_attr["regeneration"] = self.regeneration
		self.all_attr["xp"] = round(self.xp, 2)
		self.all_attr["level"] = self.level
		self.all_attr["weapon"] = str(self.weapon)
		self.all_attr["critmultiplier"] = round(self.critmultiplier,2)
		self.all_attr["max hp"] = self.max_hp
		return self.all_attr

	def updateAttrs(self, damage=0, hp=0, defense=0, speed=0, bravery=0, luck=0, regeneration=0):
		self.damage += damage
		self.damage = 1 if self.damage<1 else self.damage
		self.hp += hp
		self.hp = 1 if self.hp<1 else self.hp
		self.defense += defense
		self.defense = 1 if self.defense<1 else self.defense
		self.speed += speed
		self.speed = 1 if self.speed<1 else self.speed
		self.bravery += bravery
		self.bravery = 1 if self.bravery<1 else self.bravery
		self.luck += luck
		self.luck = 1 if self.luck<1 else self.luck
		self.regeneration += regeneration
		self.regeneration = 1 if self.regeneration<1 else self.regeneration

		self.curr_hp = self.hp*10 + self.defense
		self.max_hp = self.curr_hp
		self.mindmg += damage
		self.maxdmg += damage
		self.critmultiplier += (damage/20) + bravery*cfg.BRAVERY_CRITDMG

	def checkStats(self):
		print("\n\t{} Stats:".format(colored(self.name, self.color)))
		for k, v in sorted(self.updateAttrdict().items()):
			print("\t{: <16}: {}".format(k,v))
		print()	# print newline

	def levelUp(self):
		mixer.music.load(cfg.MUSIC_LEVELUP)
		mixer.music.play()

		new_attr_points = 0
		level_earned = int(self.xp // cfg.XP_TO_NEXTLEVEL)
		self.xp -= cfg.XP_TO_NEXTLEVEL * level_earned
		for i in range(1, level_earned+1):
			if self.level + i >= 5:
				new_attr_points += cfg.ATTR_POINTS_HILVL
			else:
				new_attr_points += cfg.ATTR_POINTS_LOWLVL

		self.level += level_earned

		levelup_message = """
{0} You are now level {3}
(1) Damage
(2) HP
(3) Defense{1}
You have {2} attribute points. Enter {2} numbers:
[Be careful! If more than {2} numbers entered, the first {2} will be applied.]
??> """.format(
		colored("==> LEVEL UP!","blue",attrs=["bold"]),
		"" if self.level<5 else "\n(4) Speed\n(5) Bravery\n(6) Luck\n(7) Regeneration",
		new_attr_points,
		self.level
	)

		new_stats = input(levelup_message)

		new_stats = new_stats.replace(" ","").replace("\t","")[:new_attr_points]
		tooshort = True if len(new_stats) < new_attr_points else False

		if self.level < 5:
			while any(i in cfg.INCORRECT_STAT_ENTRY_LO for i in new_stats) or tooshort:
				new_stats = input("Either too short or incorrect entry, try again\n??> ")
				new_stats = new_stats.replace(" ","").replace("\t","")[:new_attr_points]
				if len(new_stats) < new_attr_points:
					tooshort = True

			dmg = new_stats.count("1")
			hp = new_stats.count("2")
			defns = new_stats.count("3")
			self.updateAttrs(dmg, hp, defns)

		else:
			while any(i in cfg.INCORRECT_STAT_ENTRY_HI for i in new_stats) or tooshort:
				new_stats = input("Either too short or incorrect entry, try again\n??> ")
				new_stats = new_stats.replace(" ","").replace("\t","")[:new_attr_points]
				if len(new_stats) < new_attr_points:
					tooshort = True
				else:
					tooshort = False

			dmg = new_stats.count("1")
			hp = new_stats.count("2")
			defns = new_stats.count("3")
			spd = new_stats.count("4")
			brv = new_stats.count("5")
			lck = new_stats.count("6")
			rgn = new_stats.count("7")
			self.updateAttrs(dmg,hp,defns,spd,brv,lck,rgn)

class Weapon():
	def __init__(self, name, mindmg, maxdmg, speed):
		self.type = name
		self.name = name
		self.mindmg = mindmg
		self.maxdmg = maxdmg
		self.speed = speed
	def changeName(self, newname):
		self.name = newname + "({})".format(self.type)
	def __str__(self):
		return "{}: {} ~ {} damage, {} speed".format(self.name, self.mindmg, self.maxdmg, self.speed)

###
### Enemy Class
###
class Enemy():
	def __init__(self, level, name=None, behaviour=None, boss=None):
		self.level = level+cfg.ENEMY_MAX_LEVEL if boss else randint(
			level+cfg.ENEMY_MIN_LEVEL, level+cfg.ENEMY_MAX_LEVEL)
		if self.level < 0:
			self.level = 0
		self.color = "red"

		# xp will be increased if enemy is boss
		self.xp = 1
		if self.level > level:		# enemy is stronger
			self.xp += cfg.XP_TO_NEXTLEVEL * 3 / 20
		elif self.level < level:	# enemy is weaker
			self.xp += cfg.XP_TO_NEXTLEVEL * 1.5 / 20
		else:						# enemy is same level
			self.xp += cfg.XP_TO_NEXTLEVEL * 2 / 20
		self.xp += randint(-cfg.XP_TO_NEXTLEVEL//30, cfg.XP_TO_NEXTLEVEL//20)

		names = ["Bandit","Monavar","Mummy","Spicek","Tepelops","Wobbegangsta"]	# add more
		self.name = name if name else choice(names)

		behaviours = ["offensive", "defensive", "balanced"]+[None]*3
		self.behaviour=behaviour if behaviour else choice(behaviours)

		boss_options_hilvl = ["boss"]*5 + ["miniboss"]*10 + [None]*85
		boss_options_lowlvl = ["miniboss"]*10 + [None]*90
		if self.level == level + cfg.ENEMY_MAX_LEVEL:
			self.is_boss = boss if boss is not None else choice(boss_options_hilvl)
		elif self.level >= level:
			self.is_boss = boss if boss is not None else choice(boss_options_lowlvl)
		else:
			self.is_boss = boss

		attr_points = 0
		if self.level < 5:
			attr_points = cfg.ATTR_POINTS_INITIAL//3 + (
				(self.level-1) * cfg.ATTR_POINTS_LOWLVL if self.level>1 else 0
				)
		else:
			attr_points = cfg.ATTR_POINTS_INITIAL//2 + 3*cfg.ATTR_POINTS_LOWLVL + (self.level-4)*cfg.ATTR_POINTS_HILVL
		if self.is_boss == "miniboss":
			attr_points += cfg.ATTR_POINTS_LOWLVL * 2
			self.color = "cyan"
			self.xp += cfg.XP_TO_NEXTLEVEL // 3
		if self.is_boss == "boss":
			attr_points += cfg.ATTR_POINTS_HILVL * 2
			self.color = "magenta"
			self.xp += cfg.XP_TO_NEXTLEVEL // 5
		if cfg.DEBUGMDOE == True:
			print("ATTRPOINTS",attr_points)

		self.loot = 1
		self.loot += randint(round(self.xp/4), round(self.xp*2))

		# DETERMINE ATTRIBUTE DISTRIBUTION
		self.dmg = 0
		self.hp = 0
		self.defense = 0
		self.speed = 0
		self.luck = 0
		self.regeneration = 0
		if behaviour == "offensive":
			self.dmg += randint(attr_points*3//8, attr_points*6//8)
			attr_points -= self.dmg
			self.defense += attr_points // 3
			self.hp += (attr_points//3)
			attr_points -= self.defense * 2
			self.speed += attr_points // 3
			self.luck += attr_points // 3
			self.regeneration += attr_points // 3
			attr_points -= 3 * (attr_points//3)
			self.speed += attr_points if attr_points>0 else 0	# spend last points
		elif behaviour == "defensive":
			self.defense += randint(attr_points*3//8, attr_points*5//8)
			attr_points -= self.defense
			self.hp += (attr_points//2)
			attr_points -= attr_points//2
			self.dmg += attr_points // 2
			attr_points -= self.dmg
			self.speed += attr_points // 3
			self.luck += attr_points // 3
			self.regeneration += attr_points // 3
			attr_points -= 3 * (attr_points//3)
			self.speed += attr_points if attr_points>0 else 0	# spend last points
		elif behaviour == "balanced":
			self.defense += attr_points // 5
			self.hp += (attr_points//5)
			self.dmg += attr_points // 5
			attr_points -= 3 * (attr_points//5)
			self.speed += attr_points // 3
			self.luck += attr_points // 3
			self.regeneration += attr_points // 3
			attr_points -= 3 * (attr_points//3)
			self.speed += attr_points if attr_points>0 else 0	# spend last points
		else:
			self.defense += randint(0, attr_points-1)
			attr_points -= self.defense
			self.hp += randint(0, attr_points) if attr_points>1 else 1
			attr_points -= self.hp
			self.dmg += randint(0, attr_points) if attr_points>1 else 1
			attr_points -= self.dmg
			self.speed += randint(0, attr_points) if attr_points>1 else 1
			attr_points -= self.speed
			self.luck += randint(0, attr_points) if attr_points>1 else 1
			attr_points -= self.luck
			self.regeneration += randint(0, attr_points) if attr_points>1 else 1
			attr_points -= self.regeneration
			self.speed += attr_points if attr_points>0 else 0	# spend last points

		self.dmg += cfg.ENEMY_INITIAL_DMG
		self.hp += cfg.ENEMY_INITIAL_HP
		self.defense += cfg.ENEMY_INITIAL_DEF
		self.speed += cfg.ENEMY_INITIAL_SPD
		self.luck += cfg.ENEMY_INITIAL_LCK
		self.regeneration += cfg.ENEMY_INITIAL_RGN

		self.mindmg = randint(0, self.dmg)
		self.maxdmg = 2*self.dmg - self.mindmg
		self.max_hp = self.hp*10 + self.defense
		self.curr_hp = self.max_hp
		self.critmultiplier = randint(12,15)/10 + self.dmg/20
		self.all_attr = dict()
		if cfg.DEBUGMDOE == True:
			print("behaviour:",self.behaviour,"dmg:",self.dmg,"hp:",self.hp,"def:",self.defense)

	def __str__(self):
		return str(sorted(self.updateAttrdict().items()))

	def updateAttrdict(self):
		self.all_attr["name"] = self.name
		self.all_attr["behaviour"] = self.behaviour if self.behaviour is not None else "Random"
		self.all_attr["mindmg"] = self.mindmg
		self.all_attr["maxdmg"] = self.maxdmg
		self.all_attr["hp"] = self.hp
		self.all_attr["defense"] = self.defense
		self.all_attr["speed"] = self.speed
		self.all_attr["luck"] = self.luck
		self.all_attr["regeneration"] = self.regeneration
		self.all_attr["level"] = self.level
		self.all_attr["critmultiplier"] = round(self.critmultiplier,2)
		self.all_attr["max hp"] = self.max_hp
		return self.all_attr

	def checkStats(self):
		print("\n\t{} Stats:".format(colored(self.name, self.color)))
		for k, v in sorted(self.updateAttrdict().items()):
			print("\t{: <16}: {}".format(k,v))
		print()	# print newline

###
### Gameplay functions
###
def createNewHero():
	clear_screen()
	playername = input("Hero Name: ")
	initial_stats = input("""
Welcome {1}, prepare yourself for a great adventure!
Start by customizing your character.

(1) Damage
(2) HP
(3) Defense
You have {0} attribute points. Enter {0} numbers:
[Be careful! If more than {0} numbers entered, the first {0} will be applied.]
??> """.format(cfg.ATTR_POINTS_INITIAL, colored(playername,"green") ))
	initial_stats = initial_stats.replace(" ","").replace("\t","")[:cfg.ATTR_POINTS_INITIAL]
	tooshort = True if len(initial_stats) < cfg.ATTR_POINTS_INITIAL else False
	while any(i in cfg.INCORRECT_STAT_ENTRY_LO for i in initial_stats) or tooshort:
		initial_stats = input("Either too short or incorrect entry, try again\n??> ")
		initial_stats = initial_stats.replace(" ","").replace("\t","")[:cfg.ATTR_POINTS_INITIAL]
		if len(initial_stats) < cfg.ATTR_POINTS_INITIAL:
			tooshort = True
		else:
			tooshort = False
		#print(initial_stats, len(initial_stats), tooshort)	# DEBUG

	dmg = initial_stats.count("1")
	hp = initial_stats.count("2") + 1
	defns = initial_stats.count("3")

	player = RandomHero(playername, dmg,hp,defns)
	return player

def attack(protagonist, opponent):
	# return None if fight is not over yet (neither player nor the enemy is defeated), else return the winner
	protagonist.curr_hp += protagonist.regeneration * cfg.REGEN_MULTIPLIER
	if protagonist.curr_hp > protagonist.max_hp:
		protagonist.curr_hp = protagonist.max_hp

	dodge_rate = opponent.speed*2 - protagonist.speed//2
	dodge_rate = 1 if dodge_rate<1 else dodge_rate
	opponent_dodged = choice([1]*dodge_rate + [0]*(100-dodge_rate))
	if opponent_dodged:
		print("xx> {} has missed!".format(
			colored(protagonist.name, protagonist.color) )
		)
		time.sleep(2)
		return None

	opponent_blocked = choice([1]*opponent.defense + [0]*(100-opponent.defense))
	if opponent_blocked:
		print("xx> {}'s attack has been blocked!".format(
			colored(protagonist.name, protagonist.color) )
		)
		time.sleep(2)
		return None

	dmg = randint(protagonist.mindmg, protagonist.maxdmg)
	crit = choice([1]*protagonist.luck*2 + [0]*(100-protagonist.luck*2))
	dmg_lowerbound = 1 + protagonist.level/2
	dmg = dmg_lowerbound if (dmg-opponent.defense*cfg.DEFENSE_ABSORB)<dmg_lowerbound else dmg-opponent.defense*cfg.DEFENSE_ABSORB
	dmg = dmg*protagonist.critmultiplier if crit else dmg
	opponent.curr_hp -= dmg
	print("xx> {} has dealt {}{} damage,\n    {} has {} hp left.".format(
		colored(protagonist.name, protagonist.color),
		round(dmg,2),
		colored(" critical", attrs=["bold"]) if crit else "",
		colored(opponent.name, opponent.color),
		round(opponent.curr_hp,2)
		), end="\n"
	)
	if opponent.curr_hp <= 0:
		time.sleep(2)
		return protagonist
	else:
		time.sleep(2)
		return None

def fight(hero, enemy):
	mixer.music.load(cfg.MUSIC_BATTLE)
	mixer.music.play(loops=-1)

	hturn = 0
	eturn = 0
	winner = None
	turn = 0
	try:
		while True:
			turn += 1
			print("xx> Turn {}".format(turn))
			time.sleep(1)
			hturn += hero.speed
			eturn += enemy.speed
			if hturn >= cfg.QUICK_TURN:
				print("::> Quick Turn for {}!".format(hero.name))
				winner = attack(hero, enemy)
				if winner:
					break
				hturn -= cfg.QUICK_TURN
				turn -= 1
			if eturn >= cfg.QUICK_TURN and not hturn >= cfg.QUICK_TURN:
				print("::> Quick Turn for {}!".format(enemy.name))
				winner = attack(enemy, hero)
				if winner:
					break
				eturn -= cfg.QUICK_TURN
			else:
				winner = attack(hero, enemy)
				if winner:
					break
				winner = attack(enemy, hero)
				if winner:
					break
			# enemy may flee if attacker is the hero
			if isinstance(hero, RandomHero):
				if turn == cfg.TURNLIMIT_MAX + hero.bravery*cfg.BRAVERY_FLEEDELAY:
					break

			print("{:-<48}".format(""))
			time.sleep(1)
	except KeyboardInterrupt:
		cprint("==> {} has fled!".format(
			colored(hero.name, hero.color) ),
			attrs=["bold"],
			end="\n\n"
		)
		time.sleep(3)
		# restore HPs
		hero.curr_hp = hero.max_hp
		enemy.curr_hp = enemy.max_hp
		return

	# restore HPs
	hero.curr_hp = hero.max_hp
	enemy.curr_hp = enemy.max_hp

	print()	# print newline
	if winner == hero:
		xp_earned = enemy.xp

		loot_multiplier = [2]*(hero.luck//2) + [1.5]*(hero.luck//2) + [1.25]*hero.luck + [1]*(100-(2*(hero.luck//2)+hero.luck))
		money_earned = enemy.loot * choice(loot_multiplier)

		hero.xp += xp_earned
		hero.money += money_earned

		cprint("==> {} has won!".format(
			colored(hero.name, hero.color) ),
			attrs=["bold"]
		)
		cprint("==> Earned {} cora and {} xp.".format(
			colored(round(money_earned,2), attrs=["bold"]),
			colored(round(xp_earned,2), attrs=["bold"])	),
			end="\n\n"
		)

		if hero.xp >= cfg.XP_TO_NEXTLEVEL:
			hero.levelUp()

	elif winner == enemy:
		xp_earned = enemy.xp / 4
		hero.xp += xp_earned

		cprint("==> {} has won!".format(
			colored(enemy.name, enemy.color) ),
			attrs=["bold"]
		)
		cprint("==> Earned 0 cora and {} xp.".format(
			colored(round(xp_earned,2), attrs=["bold"])	),
			end="\n\n"
		)
	else:			# enemy has fled
		cprint("==> {} has fled!".format(
			colored(enemy.name, enemy.color) ),
			attrs=["bold"],
			end="\n\n"
		)
	time.sleep(1)

def pprint(entity):
	# Print all attributes of an entity
	for k,v in sorted(entity.__dict__.items()):
		print("{: <16}: {}".format(k,v))

###
### MAIN LOOP FUNCTIONS
###
def enemyEncounter(player):
	try:

		e = Enemy(player.level)
		print("Enemy encounter!\nA {} level {}!".format(
				colored(e.level, attrs=["bold"]),
				colored(e.name, e.color)
			)
		)

		flag_act = True
		while flag_act:
			act = input("""(1) Fight
(2) Check Enemy Stats
(3) Check Your Stats
(4) Runaway
??> """)
			if act == "1":
				print()
				fight(player, e)
				flag_act = False
			elif act == "2":
				e.checkStats()
				input("Press [ENTER] to continue...")
			elif act == "3":
				player.checkStats()
				input("Press [ENTER] to continue...")
			elif act == "4":
				cprint("==> {} has fled!".format(
					colored(player.name, player.color) ),
					attrs=["bold"],
					end="\n\n"
				)
				break
			else:
				continue
	except KeyboardInterrupt:
		return

def lootEncounter(player):
	mixer.music.load(cfg.MUSIC_LOOTENCOUNTER)
	mixer.music.play(loops=-1, start=35)

	print(choice(["You see a box in the middle of the plain.", "You spot a half-buried chest under a tree.", "You notice a bump on the sands. It is a buried crate."]))
	time.sleep(1)
	if player.bravery < (1.1*player.level - 4 + randint(-2, 0)):
		print("You are not brave enough to open it.")
		return

	good = ["You found a shiny piece of armor inside it!",
			"You find a potion, it doesn't seem too suspicious and you decide to drink it.",
			"There is nothing except just a few coras.",
			"There is a decent amount of money in it!"]

	bad = [ "As soon as you touch, it triggers an explosion and you get hurt!",
			"You find a potion, it doesn't seem too suspicious and you decide to drink it.",
			"You find a strange small item inside. While you are trying to figure it out, it releases black gas. You get dizzy and nauseous."]
	events = [good] + [bad]

	def occur(event):
		print(event)
		if event == good[0]:
			cprint("==> +3 defense", attrs=["bold"])
			exec("player.updateAttrs(defense=2)")
			return 1
		if event == good[1]:
			affected_stat = choice(["damage", "hp", "defense", "bravery", "speed", "regeneration", "luck"])
			cprint("==> +1 {}".format(affected_stat), attrs=["bold"])
			exec("player.updateAttrs("+affected_stat+"=1)")
			return 1
		if event == good[2]:
			loot = randint(5, 9)
			cprint("==> +{} cora".format(loot), attrs=["bold"])
			player.money += loot
			return 1
		if event == good[3]:
			loot = randint(20, 100)
			cprint("==> +{} cora".format(loot), attrs=["bold"])
			player.money += loot
			return 1

		if event == bad[0]:
			affected_stat = choice(["hp", "defense"])
			cprint("==> -2 {}".format(affected_stat), attrs=["bold"])
			exec("player.updateAttrs("+affected_stat+"=-2)")
			return -1
		if event == bad[1] or event == bad[2]:
			affected_stat = choice(["damage", "hp", "defense", "bravery", "speed", "regeneration", "luck"])
			cprint("==> -1 {}".format(affected_stat), attrs=["bold"])
			exec("player.updateAttrs("+affected_stat+"=-1)")
			return -1

	locked = randint(0, 1)
	if locked:
		act = input("But it is locked. What do you want to do? \n(1) Try to force open it\n(2) Leave\n??> ")
		if act == "1":
			print("...")
			time.sleep(1)
			if player.damage < 1.5 * player.level or choice([True]*1 + [False]*9):
				affected_stat = choice(["damage", "hp", "defense"])
				print("You are not strong enough, you hurt yourself while trying to open it.")
				cprint("==> -1 {}".format(affected_stat), attrs=["bold"])
				exec("player."+affected_stat+" -= 1")
				exec("player."+affected_stat+" = 1 if player."+affected_stat+"< 1 else player."+affected_stat)
				return -1
			else:
				print("You successfully open it.\n...")
				time.sleep(1)
				event = choice(good)
				occur(event)
		else:
			print("You leave...")
			time.sleep(1)
			return 0

	else:
		act = input("(1) Open it\n(2) Leave\n??> ")
		if act == "1":
			print("...")
			time.sleep(1)
			event = choice(choice(events))
			occur(event)

def store(player):
	print(player.money)
	pass

def inn(player):
	people = randint(0, 10)
	print(f"There are {people} people in the entry hall.")
	act = input("""
(1) Talk to the Innkeeper
(2) Play games with the crowd
(S) Save Game
(E) Exit the Inn
??> """).upper()

	if act == "1":
		pass
	if act == "2":
		pass
	if act == "S":
		pass
	else:
		pass

###
### SAVE & LOAD FUNCTIONS
###
def save(profile):
	# profile is a RandomHero object.
	# Return True if saved, else return False
	while True:
		save_slot_input = input("Choose a Save Slot (1) (2) (3) to save current profile. Press 'q' to cancel:\n??> ").upper()
		if save_slot_input in ["1", "2", "3"]:
			f = "save_file"+save_slot_input
			if os.path.isfile(f) and os.path.getsize(f) > 0:
				oldprofile = pickle.load(open(f, "rb"))
				confirm = input("Save Slot {} is already occupied.\nHero: {}, level {}.\nPress (1) to confirm overwriting\n??> ".format(save_slot_input, oldprofile.name, oldprofile.level))
				if confirm == "1":
					pickle.dump(profile, open(f, "wb"))
					print("Game Saved to Save Slot {}".format(save_slot_input))
					return True
				else:
					continue
			else:
				pickle.dump(profile, open(f, "wb"))
				print("Game Saved to Save Slot {}".format(save_slot_input))
				return True
		elif save_slot_input == "Q":
			print("Saving cancelled.")
			return False
		else:
			continue

def load():
	# profile is a RandomHero object.
	# return the saved profile or None depending on the inputs
	while True:
		save_slot_input = input("Choose a Save Slot (1) (2) (3) to load a profile. Press 'q' to cancel:\n??> ").upper()
		f = "save_file"+save_slot_input
		if os.path.isfile(f) and os.path.getsize(f) > 0:
			profile = pickle.load(open(f, "rb"))
			confirm = input("Save Slot {} selected.\nHero: {}, level {}. Press (1) to confirm\n??> ".format(save_slot_input, profile.name, profile.level))
			if confirm == "1":
				print("Save Slot {} is loading...".format(save_slot_input))
				return profile
			else:
				continue
		elif save_slot_input == "Q":
			print("Didn't load profile, creating new profile...")
			time.sleep(1)
			return None
		else:
			print("Selected Save Slot is empty or invalid.")
			continue

if __name__ == '__main__':

	###
	### SET THE PLAYER A PROFILE: LOAD OR CREATE A NEW ONE
	###
	player = None	# initiate player, later will become a RandomHero object by loading or creating a anew one.

	for i in range(1, 4):
		f = "save_file" + str(i)
		if os.path.isfile(f) and os.path.getsize(f) > 0:
			loadable_content = True
			break
	else:
		loadable_content = False

	if loadable_content:
		load_query = input("Saved game(s) available. Press (1) to check/load, any other key otherwise.\n??> ")
		if load_query == "1":
			player = load()
		else:
			print("Creating new profile...")
			time.sleep(1)

	if player == None:	# if a profile is not loaded, create new profile.
		player = createNewHero()
	else:
		clear_screen()
		print("Welcome back {}!\n".format(colored(player.name, player.color)))

	###
	### MAIN LOOP
	###
	while 1:
		if not mixer.music.get_busy():
			mixer.music.load(cfg.MUSIC_MAIN)
			mixer.music.play(loops=-1)

		act = input("""
(1) Explore the wild
(2) Go to the store
(3) Check your stats
(4) Save game
(C) Clear Screen
(Q) Quit game
??> """).upper()
		if act == "1":
			print()
			for i in range(randint(1, 4)):
				time.sleep(randint(5,20)/10)
				print("...")
			lootEnc_rate = 5 + player.luck
			func = choice([lootEncounter]*lootEnc_rate + [enemyEncounter]*(100-lootEnc_rate))
			func(player)
			mixer.music.stop()
		elif act == "2":
			store(player)
			time.sleep(1)
		elif act == "3":
			player.checkStats()
			input("Press [ENTER] to continue...")
		elif act == "4":
			save(player)
			time.sleep(1)

		elif act == "C":
			clear_screen()
		elif act == "Q":
			confirm = input("""Are you sure you want to quit? Press (1) to confirm.
[Remember that you can save your game before quiting, if you didn't already!]
??> """)
			time.sleep(1)
			if confirm == "1":
				sys.exit()
			else:
				continue
		else:
			continue


import cv2
import albumentations as A
from mmcls.datasets.pipelines import LoadImageFromFile, Collect, ImageToTensor, Compose
from mmcls.datasets.pipelines.transforms import Normalize
from deepcv.base import imagenet_norm
from deepcls.mmcls.pipelines import AlbuAug

def make_aug_default(img_size, is_train=True, rotate_limit=10, **kws):
    imw, imh = img_size
    color_aug = []
    if is_train:
        color_aug = [
            A.HueSaturationValue(),
            A.RandomBrightnessContrast(),
            A.ColorJitter(),
        ]

    geo_aug = []
    if is_train:
        geo_aug = [
            # A.HorizontalFlip(), # bad for keypoints
            A.ShiftScaleRotate(rotate_limit=rotate_limit, border_mode=cv2.BORDER_REPLICATE),
            A.Perspective((0.03, 0.05), pad_mode=cv2.BORDER_REPLICATE),
        ]

    transforms = [
        A.LongestMaxSize(max_size=imw),
        *color_aug,
        A.PadIfNeeded(min_height=imh, min_width=imw, border_mode=cv2.BORDER_REPLICATE),
        *geo_aug,
    ]

    return [
        AlbuAug(
            transforms,
            skip_img_without_ann=True,
            **kws
        )
    ]

img_augs = {
    'default': make_aug_default,
}

def make_pipelines(img_size, tsk='default', with_mask=True, with_contour=False, **test_kws):

    img_aug_kws = {
        'additional_targets': {},
    }

    pipelines = {}
    for tp in ['train', 'val']:
        pipe = [
            LoadImageFromFile(),
            *img_augs[tsk](
                img_size,
                is_train=(tp == 'train'),
                **img_aug_kws,
            ),
            Normalize(**imagenet_norm, to_rgb=True),
        ]
        pipe += [
            ImageToTensor(['img']),
            Collect(['img', 'gt_label'])
        ]
        pipelines[tp] = pipe

    return {
        **pipelines,
    }

def make_img_transform(img_size, norm_cfg=imagenet_norm, to_rgb=True, divisor=32):
    img_size = tuple(img_size)
    imw, imh = img_size
    return Compose([
        AlbuAug([
            A.LongestMaxSize(max_size=imw),
            A.PadIfNeeded(min_height=imh, min_width=imw, border_mode=cv2.BORDER_REPLICATE),

        ]),
        Normalize(**norm_cfg, to_rgb=to_rgb),
        ImageToTensor(['img']),
        Collect(['img']),
    ])

PIPELINES = {
    'default': {
        'pipelines': make_pipelines,
    },
}


#!/usr/bin/env python2
# vim:fileencoding=utf-8

"""
Script to download R2 shows. See `r2get -h` for usage.

Tech notes
----------

Passed parameters:

$SHOW - show name (case-insensitive)
$DATE - show date (optional)

Operation:

1. If $DATE not set, get latest show date from [1].
2. Get show $ID and cover art URL from [2].
3. Fetch show page from [3].
4. Extract RTMP stream URLs.
5. Fetch streams and cover art.
6. Convert streamdumps to a suitable container via ffmpeg.
7. Apply tags, including cover art.

References:

API = "http://r2.err.ee/api/loader"

[1] $API/airtimesforprogram/$SHOW?channel=raadio2&ShowAll=False
[2] $API/GetTimeLineDay/?$DATE
[3] http://r2.err.ee/v/$SHOW/saated/$ID
"""

from __future__ import print_function

import argparse
import base64
import calendar
import datetime
import dateutil.parser
import mutagen.id3
import mutagen.mp4
import mutagen.easymp4
import mutagen.oggvorbis
import mutagen.flac
import json
import os
import re
import stat
import subprocess
import tempfile
import sys
import urllib
import urlparse

from bs4 import BeautifulSoup

AIRTIMES_API_URL = "http://r2.err.ee/api/loader/airtimesforprogram/"
SHOW_API_URL = "http://otse.err.ee/api/schedule/"
IMG_ROOT_URL = "http://static.err.ee/gridfs"

LOGLEVEL_DEFAULT = 0
LOGLEVEL_DEBUG = 1
LOGLEVEL_INFO = 2

# API access routines

def get_last_showdate(show_id):

	# Return last airdate of a show.

	showid = re.sub(r"\s+", "", show_id)
	url = \
		AIRTIMES_API_URL + \
		showid + "?channel=raadio2&ShowAll=False"

	debug("Loading air times from " + url, LOGLEVEL_DEBUG)
	f = urllib.urlopen(url)
	tree = json.load(f)

	if ((type(tree) is not list) or len(tree) == 0):
		err("Did not retrieve any show times for \"" + show_id + "\"")
	return parse_date(tree[0]["AirDate"])

def get_show_attrs(show_id, date, partial_name):

	# Return the canonical name, GUID and artwork URL
	# of a show on a given date.

	url = \
		SHOW_API_URL + "GetTimelineDay?channel=r2" + \
		"&year=" + str(date.year) + "&month=" + str(date.month) + "&day=" + str(date.day)

	debug("Fetching show attributes from " + url, LOGLEVEL_DEBUG)

	f = urllib.urlopen(url)
	tree = json.load(f)
	lname = show_id.lower()
	arturl = None
	artopts = None

	def is_name_match(header_entry):
		header_entry = header_entry.lower()

		if (partial_name):
			return (True if header_entry.find(lname) != -1 else False)
		else:
			return header_entry == lname

	for i in tree:
		header_entry = i["Header"];
		debug("\tHeader entry: " + header_entry, LOGLEVEL_INFO)

		if (is_name_match(header_entry)):
			imgurl = None
			pageurl = None

			if (i["Image"]):
				imgurl = ""
				imgurl += IMG_ROOT_URL + "/" + i["Image"]
				if (i["ImageResizerOptions"]):
					imgurl += i["ImageResizerOptions"]
				else:
					imgurl += "?width=1200"

			if (i["Url"]):
				pageurl = i["Url"]
			else:
				raise KeyError("Cannot get attribute \"Url\" for \"" + show_id + "\"")

			return (
				i["Header"],
				pageurl,
				imgurl
			)

	raise KeyError(
		"Cannot get show attributes for \"" + show_id +
		"\" on " + str(date)
	)

def get_show_streams(url):

	# Return the RTMP stream URLs of a show with a given GUID. Attempts to
	# scrape for "RR.*m4a" streams first; if none found, resorts to any
	# *.m4a streams.

	streams = []
	f = urllib.urlopen(url)
	soup = BeautifulSoup(f, "html.parser")

	# Helper routine for tight / loose condition

	def find_streams(soup, tightmatch):
		found_streams = []
		tightmatch = r".*?RR" if tightmatch else ""

		for stag in soup.findAll("script"):
			suris = re.findall(r"media\.err\.ee" + tightmatch + ".*?m4a", str(stag))

			for suri in (suris):
				suri = "rtmp://" + re.sub("r2/@", "r2/", suri);
				found_streams.append(suri)

		return found_streams

	# Scrape the DOM

	debug("Scraping for show streams from " + url, LOGLEVEL_DEBUG)
	streams = find_streams(soup, True)

	if (not len(streams)):
		debug("Cannot find any RR* streams, attempting to scrape any streams", LOGLEVEL_DEBUG)
		streams = find_streams(soup, False)

	streams = list_uniq(streams)

	if (len(streams) < 1):
		raise RuntimeError("Cannot retrieve any stream URLs from " + url)
	return streams

# Audio retrieval and packaging routines

def download_audio(streams, retries, quick_test=False):

	# Dump raw RTMP streams into temporary files.

	dumps = []

	for s in streams:
		d = tempfile.NamedTemporaryFile(suffix='.m4a')
		args = ["rtmpdump", "-v", "-#", "-o", d.name, "-r", s]
		resume_flag = False

		debug("Dumping " + s + " to " + d.name)

		if (quick_test):
			args += ["-B", "30"]  # call instead check_call because
			subprocess.call(args) # rtmpdump returns non-zero w/ -B
		else:
			for i in range(0, retries):
				if (i > 0):
					debug("Retrying (" + str(i+1) + " / " + str(retries) + ")")
					if (not resume_flag):
						args += ["-e"]
						resume_flag = True

				try:
					subprocess.check_call(args)
				except subprocess.CalledProcessError as e:
					if (e.returncode == 2 and i < (retries-1)): # incomplete transfer
						continue
					else:
						err("Failed fetching stream after " + str(retries) + " times", e)
				break

		dumps.append(d)

	return dumps

def package_audio(show_id, showname, showdate, show_imgurl, infns, outputs):

	# Package dumped raw RTMP stream into a proper m4a (aka ipod)
	# container, apply tags including cover art. infns can be a list of
	# strings (file names) or a list of NamedTemporaryFiles. outputs is
	# a dict of output ID - directory mappings.

	showfn_prefix = re.sub(r"\s+", "-", show_id.lower())

	# Fetch cover image

	coverf = urllib.urlopen(show_imgurl)
	if (coverf.info().gettype() != "image/jpeg" or coverf.getcode() != 200):
		warn("Cannot retrieve JPEG cover art")
	cover = coverf.read()

	# Loop over input stream dumps

	for i, infn in enumerate(infns):
		if (len(infns) <= 1):
			showfn_suffix = "-1"
		else:
			showfn_suffix = "-" + str(i + 1)
		if (type(infn) is not str):
			infn = infn.name

		show_index = re.sub(r"-", " ", showfn_suffix)
		show_title = showname + " " + str(showdate) + show_index

		# Loop over output formats

		for k in outputs:
			outdir = outputs[k]
			showfn = outdir + "/" + showfn_prefix + showfn_suffix

			if (k == "mp3"):
				showfn += ".mp3"
				package_mp3(infn, showfn, show_title, cover)
			if (k == "ogg"):
				showfn += ".ogg"
				package_ogg(infn, showfn, show_title, cover)
			elif (k == "mp4"):
				showfn += ".m4a"
				package_mp4(infn, showfn, show_title, cover)

def package_mp4(infn, outfn, title, cover):
	subprocess.check_call(
		["ffmpeg", "-y", "-i", infn, "-acodec", "copy", outfn])

	tags = mutagen.mp4.MP4(outfn)
	cover = [mutagen.mp4.MP4Cover(cover)]

	tags["\xa9ART"] = "R2"
	tags["\xa9nam"] = title
	tags["\xa9alb"] = "R2"
	tags["covr"] = cover
	tags.save()

def package_mp3(infn, outfn, title, cover):
	subprocess.check_call(
		["ffmpeg", "-y", "-i", infn, "-acodec", "libmp3lame", "-q:a", "1", outfn])

	tags = mutagen.id3.ID3(outfn)
	tags.add(mutagen.id3.TPE1(encoding=3, text="R2"))
	tags.add(mutagen.id3.TIT2(encoding=3, text=title))
	tags.add(mutagen.id3.TALB(encoding=3, text="R2"))
	tags.add(mutagen.id3.APIC(encoding=3, type=3, data=cover))
	tags.save()

def package_ogg(infn, outfn, title, cover):
	subprocess.check_call(
		["ffmpeg", "-y", "-i", infn, "-codec:a", "libvorbis", "-qscale:a", "6", outfn])

	ogg = mutagen.oggvorbis.OggVorbis(outfn)
	ogg.tags["artist"] = u"R2"
	ogg.tags["title"] = title
	ogg.tags["album"] = u"R2"
	write_ogg_image(ogg, cover)
	ogg.save()

# Auxiliary routines

def parse_date(s):

	# Coerce a string into a date object.

	d = dateutil.parser.parse(s)
	return datetime.date(d.year, d.month, d.day)

def parse_command_line():
	parser = argparse.ArgumentParser(description = "Fetch a show from R2.")
	parser.add_argument(
		"-d", "--date",
		help="specify desired show airdate, e.g. \"15\", \"2015-02-12\""
	)
	parser.add_argument(
		"-s", "--skip",
		help="skip download, use specified filename as audio input"
	)
	parser.add_argument(
		"-q", "--quick-test",
		action="store_true",
		help="quick sanity test of the pipeline, download 30 first seconds only"
	)
	parser.add_argument(
		"-p", "--partial-name",
		action="store_true",
		help="allow partial match for show name; only makes sense with -d"
	)
	parser.add_argument(
		"-v", "--verbose",
		action="count",
		help="increase verbosity"
	)
	parser.add_argument(
		"-r", "--retry", type=int, default=5,
		help="number of retries in case of incomplete transfers, default 5"
	)
	parser.add_argument(
		"-D", "--mp4-dir", default=".",
		help="mp4 (unmodified stream) output directory"
	)
	parser.add_argument(
		"--mp3-dir", default=None,
		help="mp3 output directory"
	)
	parser.add_argument(
		"--ogg-dir", default=None,
		help="ogg output directory"
	)
	parser.add_argument("show_id")
	return parser.parse_args()

def gather_outputs(args):
	o = dict()

	if (args.mp4_dir):
		o["mp4"] = args.mp4_dir
	if (args.mp3_dir):
		o["mp3"] = args.mp3_dir
	if (args.ogg_dir):
		o["ogg"] = args.ogg_dir

	for k in o:
		if (not os.access(o[k], os.F_OK or os.W_OK)):
			err(o[k] + " does not exist or isn't writable")

	return o

def write_ogg_image(ogg, cover):

	# Write an image block to OGG Vorbis, see
	# http://mutagen.readthedocs.io/en/latest/user/vcomment.html

	picture = mutagen.flac.Picture()
	picture.data = cover
	picture.type = 3
	picture.mime = u"image/jpeg"

	base64_picture = base64.b64encode(picture.write())
	ogg["metadata_block_picture"] = [base64_picture.decode("ascii")]

def debug(msg, verbosity=0):
	if (verbosity > (debug.verbosity or 0)):
		return
	try:
		print(msg, file=sys.stderr)
	except UnicodeEncodeError as e:
		err(
			"Please set PYTHONIOENCODING=UTF-8 to avoid encoding errors " +
			"in case of badly detected or non-Unicode stderr", e
		)

def warn(msg, is_error=0):
	if (is_error):
		msg = "ERROR: " + msg
	else:
		msg = "WARNING: " + msg
	debug(msg)

def err(msg, e=None):

	# If exception `e` is passed, raise it instead of sys.exit-ing

	warn(msg, is_error=1)

	if (e == None):
		sys.exit(1)
	else:
		raise e

def debug_set_verbosity(v):
	debug.verbosity = v;

def list_uniq(l):
	s = set()
	r = []

	for i in (l):
		if (i not in s):
			r.append(i)
			s.add(i)

	return r

def main():

	# show_id is the identifier from the command line, possibly
	# partial, used for file names. show_name is the name from R2.

	args = parse_command_line()
	show_id = args.show_id.strip()
	streams = None
	infns = None
	outputs = None

	debug_set_verbosity(args.verbose)
	outputs = gather_outputs(args)

	if (args.skip):
		infns = [args.skip]
	if (args.date):
		showdate = parse_date(args.date)
	else:
		showdate = get_last_showdate(show_id)

	(showname, show_url, show_imgurl) = \
		get_show_attrs(show_id, showdate, args.partial_name)
	debug("Show name:\t" + showname)
	debug("Show date:\t" + str(showdate))
	debug("Image URL:\t" + show_imgurl)

	if (not infns):
		streams = get_show_streams(show_url)
		debug("Stream URLs:\t" + str(streams))
		infns = download_audio(streams, args.retry, args.quick_test)
	package_audio(show_id, showname, showdate, show_imgurl, infns, outputs)

main()


from dragonfly import (Grammar, AppContext, MappingRule, Dictation, Key, Text, Integer, Mimic)

putty_context = AppContext(executable="putty")
kitty_context = AppContext(executable="kitty")
virtualbox_context = AppContext(executable="virtualbox")
bash_context = AppContext(executable="bash")
sh_context = AppContext(executable="sh")
conemu64_context = AppContext(executable="ConEmu64")
grammar = Grammar("bash", context=(putty_context | sh_context | bash_context | kitty_context | virtualbox_context | conemu64_context))
noSpaceNoCaps = Mimic("\\no-caps-on") + Mimic("\\no-space-on")

rules = MappingRule(
    name = "bash",
    mapping = {
      "watch macros": Text("cd ~/Documents/GitHub/code-by-voice && ./node_modules/.bin/gulp") + Key('enter'),

      "pseudo": Text("sudo "),

      # navigation
      "make der": Text("mkdir ") + noSpaceNoCaps,
      "CD": Text("cd ") + noSpaceNoCaps,
      "push dee": Key("p,u,s,h,d,space"),
      "pop dee": Key("p,o,p,d,enter"),
      "dirs": Key("d,i,r,s,enter"),
      "up directory": Text("cd ..") + Key('enter'),
      "list files": Text("ls -l") + Key("enter"),
      "LS": Text("ls"),
      "LS long": Text("ls -l"),
      "go home": Text("cd ~") + Key("enter"),
      "run": Text("./"),
      "cancel": Key("c-c"),
      "exit": Key("c-d"),

      # particular programs
      "aptitude install" : Text("apt-get install "),
      "pseudo aptitude install" : Text("sudo apt-get install "),
      "them": Text("vim "),
      "W get": Text("wget "),
      "flex": Text("flex "),
      "GCC": Text("gcc "),

      "make": Text("make "),
      "make test": Text("make test") + Key("enter"),
      "make all": Text("make -B") + Key("enter"),
      "windows make": Text("mingw32-make.exe") + Key("enter"),
      "windows make all": Text("mingw32-make.exe -B") + Key("enter"),

      "docker": Text("docker "),
      "docker run": Text("docker run "),

      "NPM": Text("npm "),
      "NPM install": Text("npm install"),

      "ebb": Text("eb "),
      "ebb in it": Text("eb init "),
      "ebb create": Text("eb create "),

      "vagrant upper": Text("vagrant up"),
      "vagrant ssh": Text("vagrant ssh"),
      "vagrant destroy": Text("vagrant destroy"),
      "vagrant reload": Text("vagrant reload"),
      "vagrant reload [dash dash] provision": Text("vagrant reload --provision"),
      "CD slash vagrant": Text("cd /vagrant"),

      # tmux
      "tmux attach": Text("tmux attach") + Key("enter"),
      "tmux attach dash tee": Text("tmux attach -t "),
      "tmux new": Text("tmux new -s "),
      "tmux Ellis": Text("tmux ls") + Key("enter"),
      "tmux": Text("tmux"),

      "term detach": Key("c-b, d"),
      "term prefix": Key("c-b"),
      "term vertical": Key("c-b,percent"),
      "term split": Key("c-b,dquote"),
      "term west": Key("c-b,left"),
      "term east": Key("c-b,right"),
      "term north": Key("c-b,up"),
      "term south": Key("c-b,down"),
      "term create window": Key("c-b,c"),
      "term list windows": Key("c-b,w"),
      "term next window": Key("c-b,n"),
      "term previous window": Key("c-b,p"),
      "term name window": Key("c-b,comma"),
      "term zoom": Key("c-b,z"),
      "term copy": Key("c-b,lbracket"),
      "term pane <n>": Key("c-b,q,%(n)d"),
      "term window <n>": Key("c-b,w,%(n)d"),
      "term reload config": Key("c-b,colon") + Text("source-file ~/.tmux.conf") + Key("enter"),

      # git
      "git": Text("git "),
      "get": Text("git "),
      "status": Text("status"),
      "diff": Text("diff"),
      "commit": Text("commit"),
      "origin": Text("origin "),

      "get add ": Text("git add "),
      "get add [dash dash] patch": Text("git add --patch"),
      "get branch": Text("git branch "),
      "get check out": Text("git checkout "),
      "get check out dash bee": Text("git checkout -b "),
      "get clone": Text("git clone "),
      "get commit": Text("git commit -v") + Key('enter'),
      "get commit amend": Text("git commit -v --amend") + Key('enter'),
      "get diff": Text("git diff") + Key("enter"),
      "get fetch": Text("git fetch "),
      "get log ": Text("git log --decorate") + Key("enter"),
      "get merge": Text("git merge "),
      "get pull": Text("git pull") + Key("enter"),
      "get pull [dash dash] rebase": Text("git pull --rebase") + Key("enter"),
      "get push": Text("git push "),
      "get status": Text("git status -uno") + Key("enter"),
      "get status pipe less": Text("git status | less") + Key('enter'),
      "get short status": Text("git status -sb -uno") + Key("enter"),
      "get stash": Text("git stash "),
      "get stash save": Text("git stash save") + Key('enter'),
      "get stash pop": Text("git stash pop") + Key('enter'),
      "get reset": Text("git reset "),
      "get reset hard": Text("git reset --hard "),
      "get reset hard head": Text("git reset --hard HEAD"),
      "get reset soft": Text("git reset --soft "),

      "gerrit push": Text("git push origin HEAD:refs/for/"),
      "get review": Text("/c/Python27/Scripts/git-review.exe "),
      "get review dash dee": Text("/c/Python27/Scripts/git-review.exe -d "),
      "get review dash dee <n>": Text("/c/Python27/Scripts/git-review.exe -d %(n)d"),

      "get kay": Text("gitk") + Key("enter"),
      },
    extras = [
        Dictation("text"),
        Integer("n", 0, 20000),
      ],
    defaults = {
      "n" : 1
      }
    )

grammar.add_rule(rules)

grammar.load()

def unload():
  global grammar
  if grammar: grammar.unload()
  grammar = None


from __future__ import with_statement #compatibility for Live 9, need to be written at the first line of the script
import Live #you import Live, in order to be able to use its components
from _Framework.ButtonElement import ButtonElement

IS_MOMENTARY=True

class VolumeButton(ButtonElement):
    __module__=__name__
    __doc__="Sparkle function for Volume buttons"
    def __init__(self, is_momentary, msg_type, channel, identifier, parent):
        ButtonElement.__init__(self, is_momentary, msg_type, channel, identifier)
        self.status=False
        self.identifier=identifier
        self.parent=parent
        self.name= 'Volume button' + str(identifier)
##########################################################volume buttons:
    def volume_button_value(self,value,sender):
        if self.parent.actual_clipslot!=None:
            if value>0:
                self.parent.jog_wheel.clear_value_listeners()
                self.parent.jog_wheel.add_value_listener(self.change_volume,identify_sender=False)
                self.parent.actual_volume=sender
                for element in self.parent.volume_buttons:
                    self.turn_led_off(element.identifier)
                for index in range(sender.identifier,33):
                    self.turn_led_on(index)
            else:
                self.parent.jog_wheel.clear_value_listeners()
                self.parent.jog_wheel.add_value_listener(self.parent.change_session,identify_sender=False)

##########################################################jog wheel
    def change_volume(self,value):
        if value==63:
            self.parent.actual_volume.volume=self.parent.actual_volume.volume-5
        elif value==65:
            self.parent.actual_volume.volume=self.parent.actual_volume.volume+5

#########################################################general
    def turn_led_on(self,value):
        self._send_midi((144,value,64))
    def turn_led_off(self,value):
        self._send_midi((128,value,64))


#!/usr/bin/env python3

#    Copyright 2016 RIFT.IO Inc
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

"""
#
#

@file test_startstop.py
@author Paul Laidler (Paul.Laidler@riftio.com)
@date 12/17/2015
@brief System test of launchpad start and stop functionality
"""

import pytest

import gi
gi.require_version('RwMcYang', '1.0')
from gi.repository import RwMcYang

@pytest.fixture(scope='module')
def proxy(request, mgmt_session):
    '''fixture which returns a proxy to RwMcYang

    Arguments:
        request       - pytest fixture request
        mgmt_session  - mgmt_session fixture - instance of a rift.auto.session class
    '''
    return mgmt_session.proxy(RwMcYang)

@pytest.mark.depends('launchpad')
@pytest.mark.incremental
class TestLaunchpadStartStop:

    @pytest.mark.feature('mission-control')
    def test_stop_launchpad(self, proxy, mgmt_domain_name):
        '''Invoke stop launchpad RPC

        Asserts:
            Launchpad begins test in state 'started'
            Launchpad finishes test in state 'stopped'
        '''

        proxy.wait_for(
                "/mgmt-domain/domain[name='%s']/launchpad/state" % mgmt_domain_name,
                'started',
                timeout=10,
                fail_on=['crashed'])
        stop_launchpad_input = RwMcYang.StopLaunchpadInput(mgmt_domain=mgmt_domain_name)
        stop_launchpad_output = proxy.rpc(stop_launchpad_input)
        proxy.wait_for(
                "/mgmt-domain/domain[name='%s']/launchpad/state" % mgmt_domain_name,
                'stopped',
                timeout=120,
                fail_on=['crashed'])

    @pytest.mark.feature('mission-control')
    def test_start_launchpad(self, proxy, mgmt_domain_name, launchpad_scraper):
        '''Invoke start launchpad RPC

        Asserts:
            Launchpad begins test in state 'stopped'
            Launchpad finishes test in state 'started'
        '''
        proxy.wait_for(
                "/mgmt-domain/domain[name='%s']/launchpad/state" % mgmt_domain_name,
                'stopped',
                timeout=10,
                fail_on=['crashed'])
        start_launchpad_input = RwMcYang.StartLaunchpadInput(mgmt_domain=mgmt_domain_name)
        start_launchpad_output = proxy.rpc(start_launchpad_input)
        proxy.wait_for(
                "/mgmt-domain/domain[name='%s']/launchpad/state" % mgmt_domain_name,
                'started',
                timeout=400,
                fail_on=['crashed'])
        launchpad_scraper.reset()


from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.offer, name='offer-main'),
    url(r'^teacher$', views.proposal, name='my-proposal'),
    url(r'^teacher/(?P<slug>[\w\-_]+)$', views.proposal, name='my-proposal-show'),
    url('^add$', views.proposal_edit, name='proposal-form'),
    url('^manage/proposals$', views.manage, name='manage'),
    url('^manage/select_for_voting$', views.select_for_voting),
    url('^manage/groups$', views.all_groups),
    url(r'^manage/groups/(?P<slug>[\w\-_]+)', views.course_groups),
    url(r'^(?P<slug>[\w\-_]+)/accept', views.proposal_accept, name='proposal-accept'),
    url(r'^(?P<slug>[\w\-_]+)/review', views.proposal_for_review, name='proposal-review'),
    url(r'^(?P<slug>[\w\-_]+)/edit', views.proposal_edit, name='proposal-edit'),
    url(r'^(?P<slug>[\w\-_]+)', views.offer, name='offer-page'),
]


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
intensity_normalization.normalize.lsq

fit the

Author: Jacob Reinhold (jacob.reinhold@jhu.edu)

Created on: Feb 23, 2020
"""

import logging
import os

import nibabel as nib
import numpy as np

from intensity_normalization.utilities import io
from intensity_normalization.utilities import mask as mask_util
from .fcm import fcm_normalize, find_tissue_mask

logger = logging.getLogger(__name__)

def lsq_normalize(img_dir, mask_dir=None, output_dir=None, write_to_disk=True):
    """
    normalize intensities of a set of MR images by minimizing the squared distance
    between CSF, GM, and WM means within the set

    Args:
        img_dir (str): directory containing MR images
        mask_dir (str): directory containing masks for MR images
        output_dir (str): directory to save images if you do not want them saved in
            same directory as data_dir
        write_to_disk (bool): write the normalized data to disk or nah

    Returns:
        normalized (np.ndarray): last normalized image from img_dir
    """
    input_files = io.glob_nii(img_dir)
    if output_dir is None:
        out_fns = [None] * len(input_files)
    else:
        out_fns = []
        for fn in input_files:
            _, base, ext = io.split_filename(fn)
            out_fns.append(os.path.join(output_dir, base + '_lsq' + ext))
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

    mask_files = [None] * len(input_files) if mask_dir is None else io.glob_nii(mask_dir)

    standard_tissue_means = None
    normalized = None
    for i, (img_fn, mask_fn, out_fn) in enumerate(zip(input_files, mask_files, out_fns)):
        _, base, _ = io.split_filename(img_fn)
        logger.info('Transforming image {} to standard scale ({:d}/{:d})'.format(base, i + 1, len(input_files)))
        img = io.open_nii(img_fn)
        mask = io.open_nii(mask_fn) if mask_fn is not None else None
        tissue_mem = mask_util.fcm_class_mask(img, mask)
        if standard_tissue_means is None:
            csf_tissue_mask = find_tissue_mask(img, mask, tissue_type='csf')
            csf_normed_data = fcm_normalize(img, csf_tissue_mask).get_fdata()
            standard_tissue_means = calc_tissue_means(csf_normed_data, tissue_mem)
            del csf_tissue_mask, csf_normed_data
        img_data = img.get_fdata()
        tissue_means = calc_tissue_means(img_data, tissue_mem)
        sf = find_scaling_factor(tissue_means, standard_tissue_means)
        logger.debug('Scaling factor for {}: {:0.3e}'.format(base, sf))
        normalized = nib.Nifti1Image(sf * img_data, img.affine, img.header)
        if write_to_disk:
            io.save_nii(normalized, out_fn, is_nii=True)

    return normalized

def calc_tissue_means(img, tissue_mem):
    def weighted_avg(w, x):
        return (w * x).sum() / w.sum()
    tissue_types = tissue_mem.shape[-1]
    weighted_avgs = [weighted_avg(tissue_mem[..., i], img) for i in range(tissue_types)]
    return np.asarray([weighted_avgs]).T

def find_scaling_factor(tissue_means, standard_tissue_means):
    sf = (tissue_means.T @ standard_tissue_means) / (tissue_means.T @ tissue_means)
    return sf.squeeze()


import numpy as np
import matplotlib.pyplot as plt

import pandas as pd
from sklearn.datasets import load_boston
boston_dataset = load_boston()

boston = pd.DataFrame(boston_dataset.data, columns=boston_dataset.feature_names)
boston['MEDV'] = boston_dataset.target
X = pd.DataFrame(np.c_[boston['LSTAT'], boston['RM']], columns = ['LSTAT','RM'])
Y = boston['MEDV']

from sklearn.model_selection import train_test_split

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2, random_state=5)
print(X_train.shape)
print(X_test.shape)
print(Y_train.shape)
print(Y_test.shape)
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

lin_model = LinearRegression()
lin_model.fit(X_train, Y_train)
# model evaluation for training set
y_train_predict = lin_model.predict(X_train)
rmse = (np.sqrt(mean_squared_error(Y_train, y_train_predict)))
r2 = r2_score(Y_train, y_train_predict)

print("The model performance for training set")
print("--------------------------------------")
print('RMSE is {}'.format(rmse))
print('R2 score is {}'.format(r2))
print("\n")

# model evaluation for testing set
y_test_predict = lin_model.predict(X_test)
rmse = (np.sqrt(mean_squared_error(Y_test, y_test_predict)))
r2 = r2_score(Y_test, y_test_predict)

print("The model performance for testing set")
print("--------------------------------------")
print('RMSE is {}'.format(rmse))
print('R2 score is {}'.format(r2))


# -*- coding:utf-8 -*-
# author: xiaojie
# datetime: 2020/5/12 10:57
# software: PyCharm

from bert_classification_utils import init_logger, DataProcess
from trainer import Trainer
import torch
from tqdm import tqdm
import logging
import random
from argparse import Namespace
from torch.utils.data import TensorDataset
import numpy as np
import json
import os
import codecs
os.environ["CUDA_VISIBLE_DEVICES"] = "1"
init_logger()

logger = logging.getLogger(__name__)

class BertClassificationTrainModelHandler(DataProcess):

    def __init__(self, config_params):

        config_params.update(config_params.get("hyper_param", {}))
        self.config = Namespace(**config_params)
        self.config.no_cuda = False
        # self.config.model_name_or_path = "E:\\nlp_tools\\bert_models\\bert-base-chinese"
        self.config.model_name_or_path = "/home/hemei/xjie/bert_models/bert-base-chinese"

        self.ADDITIONAL_SPECIAL_TOKENS = self.config.ADDITIONAL_SPECIAL_TOKENS
        self.ADDITIONAL_SPECIAL_TOKENS = ["<e1>", "</e1>", "<e2>", "</e2>"]
        super(BertClassificationTrainModelHandler, self).__init__(self.config)
        # token
        self.tokenizer = self.load_tokenizer(self.config)
        ##########

        ##########
        self.model_save_path = self.config.model_dir

    def data_process(self):
        # 获取正负样本

        data, labels, max_seq_len, other_size = self.get_data_1()

        label_id = {l: ind for ind, l in enumerate(labels)}
        id_label = {v: k for k, v in label_id.items()}
        self.config.max_seq_len = max_seq_len
        self.config.labels = labels
        self.config.label_id = label_id
        self.config.id_label = id_label
        self.config.other_size = other_size

        # data = data[:100]

        random.shuffle(data)
        train_len = int(len(data) * 0.8)
        train_data_ = data[:train_len]
        test_data_ = data[train_len:]

        self.train_data = self._get_data(train_data_, label_id, "train")

        self.test_data = self._get_data(test_data_, label_id, "test")

        self.dev_data = self.test_data

    def init_workflow(self):
        pass

    def fit(self):
        if not os.path.exists(self.model_save_path):
            os.makedirs(self.model_save_path, exist_ok=True)

        self.config.model_save_path = self.model_save_path

        with codecs.open(os.path.join(self.model_save_path, 'params_config.json'), 'w', encoding='utf-8') as fd:
            json.dump(vars(self.config), fd, indent=4, ensure_ascii=False)

        self.trainer = Trainer(self.config,
                               train_dataset=self.train_data,
                               dev_dataset=self.dev_data,
                               test_dataset=self.test_data)
        self.trainer.train()

    def eval(self):
        self.trainer.load_model()
        eval_results = self.trainer.evaluate1("test")
        print(eval_results)

if __name__ == '__main__':
    config_params = {
        "algorithm_id": 19,
        "hyper_param_strategy": "CUSTOMED",
        "hyper_param": {
            "ADDITIONAL_SPECIAL_TOKENS": [],
            "model_dir": "./model_all",
            "data_dir": "./data",
            "model_type": "bert",
            "seed": 1234,
            "train_batch_size": 32,
            "eval_batch_size": 32,
            "max_seq_len": 195,
            "max_seq_len2": 256,
            "learning_rate": 5e-5,
            "num_train_epochs": 10,  # 5， 20
            "weight_decay": 0.0,
            "gradient_accumulation_steps": 1,
            "adam_epsilon": 1e-8,
            "max_grad_norm": 1.0,
            "max_steps": -1,
            "warmup_steps": 0,
            "dropout_rate": 0.1,
            "logging_steps": 1000,
            "save_steps": 1000,
            "neg_num": 5,
            "no_cuda": False,
            "ignore_index": 0,
            "do_train": True,
            "do_eval": True,
            "sentence_num": 2,
            "is_heading": True,
            "ntn": False
        },
        "train_file_url": [],
        "job_name": "bert_classification_0"
    }

    config_params["hyper_param"]["model_dir"] = "./model_{}".format("all")
    bt = BertClassificationTrainModelHandler(config_params)
    bt.data_process()
    bt.fit()
    bt.eval()

Sichuan Innovation Digital Contest/src/bert_classification_train.py


#!/usr/bin/env python3
# coding: utf-8

import os
import subprocess
import threading
import datetime
import logging
import logging.handlers
import psutil
import time
import argparse
import sys
import signal
from collections import defaultdict
import daemon
from daemon import pidfile

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASE_DIR)

logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")

os.environ["PYTHONIOENCODING"] = "UTF-8"
APPS_DIR = os.path.join(BASE_DIR, 'apps')
TMP_DIR = os.path.join(BASE_DIR, 'tmp')
HTTP_HOST = '0.0.0.0'
HTTP_PORT = 8000
WS_PORT = 8002
DEBUG = False
LOG_LEVEL = 'INFO'

START_TIMEOUT = 40
WORKERS = 4
DAEMON = False
LOG_KEEP_DAYS = 7
logging.basicConfig(
    format='%(asctime)s %(message)s', level=logging.INFO,
    datefmt='%Y-%m-%d %H:%M:%S'
)

EXIT_EVENT = threading.Event()
LOCK = threading.Lock()
files_preserve = []
STOP_TIMEOUT = 10

logger = logging.getLogger()

try:
    os.makedirs(TMP_DIR, exist_ok=True)
    os.makedirs(os.path.join(BASE_DIR, "data", "static"), exist_ok=True)
    os.makedirs(os.path.join(BASE_DIR, "data", "media"), exist_ok=True)
except:
    pass

def check_database_connection():
    os.chdir(os.path.join(BASE_DIR, 'apps'))
    for i in range(60):
        logging.info("Check database connection ...")
        code = subprocess.call("python manage.py showmigrations users ", shell=True)
        if code == 0:
            logging.info("Database connect success")
            return
        time.sleep(1)
    logging.info("Connection database failed, exist")
    sys.exit(10)

def make_migrations():
    logging.info("Check database structure change ...")
    os.chdir(os.path.join(BASE_DIR, 'apps'))
    logging.info("Migrate model change to database ...")
    subprocess.call('python3 manage.py migrate', shell=True)

def collect_static():
    logging.info("Collect static files")
    os.chdir(os.path.join(BASE_DIR, 'apps'))
    command = 'python3 manage.py collectstatic --no-input -c &> /dev/null '
    subprocess.call(command, shell=True)
    logging.info("Collect static files done")

def prepare():
    check_database_connection()
    make_migrations()
    collect_static()

def check_pid(pid):
    """ Check For the existence of a unix pid. """
    try:
        os.kill(pid, 0)
    except (OSError, ProcessLookupError):
        return False
    else:
        return True

def get_pid_file_path(s):
    return os.path.join(TMP_DIR, '{}.pid'.format(s))

def get_pid_from_file(path):
    if os.path.isfile(path):
        with open(path) as f:
            try:
                return int(f.read().strip())
            except ValueError:
                return 0
    return 0

def get_pid(s):
    pid_file = get_pid_file_path(s)
    return get_pid_from_file(pid_file)

def is_running(s, unlink=True):
    pid_file = get_pid_file_path(s)

    if os.path.isfile(pid_file):
        pid = get_pid(s)
        if pid == 0:
            return False
        elif check_pid(pid):
            return True

        if unlink:
            os.unlink(pid_file)
    return False

def parse_service(s):
    all_services = [
        'gunicorn', 'celery_ansible', 'celery_default',
        'beat', 'flower', 'daphne',
    ]
    if s == 'all':
        return all_services
    elif s == "web":
        return ['gunicorn', 'flower', 'daphne']
    elif s == 'ws':
        return ['daphne']
    elif s == "task":
        return ["celery_ansible", "celery_default", "beat"]
    elif s == "celery":
        return ["celery_ansible", "celery_default"]
    elif "," in s:
        services = set()
        for i in s.split(','):
            services.update(parse_service(i))
        return services
    else:
        return [s]

def get_start_gunicorn_kwargs():
    print("\n- Start Gunicorn WSGI HTTP Server")
    prepare()
    bind = '{}:{}'.format(HTTP_HOST, HTTP_PORT)
    log_format = '%(h)s %(t)s "%(r)s" %(s)s %(b)s '

    cmd = [
        'gunicorn', 'kubeoperator.wsgi',
        '-b', bind,
        '-k', 'gthread',
        '--threads', '10',
        '-w', str(WORKERS),
        '--max-requests', '4096',
        '--access-logformat', log_format,
        '--access-logfile', '-'
    ]

    if DEBUG:
        cmd.append('--reload')
    return {'cmd': cmd, 'cwd': APPS_DIR}

def get_start_daphne_kwargs():
    print("\n- Start Daphne ASGI WS Server")
    cmd = [
        'daphne', 'kubeoperator.asgi:application',
        '-b', HTTP_HOST,
        '-p', str(WS_PORT),
    ]
    return {'cmd': cmd, 'cwd': APPS_DIR}

def get_start_celery_ansible_kwargs():
    print("\n- Start Celery as Distributed Task Queue: Ansible")
    return get_start_worker_kwargs('ansible', 4)

def get_start_celery_default_kwargs():
    print("\n- Start Celery as Distributed Task Queue: Celery")
    return get_start_worker_kwargs('celery', 2)

def get_start_worker_kwargs(queue, num):
    # Todo: Must set this environment, otherwise not no ansible result return
    os.environ.setdefault('PYTHONOPTIMIZE', '1')
    os.environ.setdefault('ANSIBLE_FORCE_COLOR', 'True')

    if os.getuid() == 0:
        os.environ.setdefault('C_FORCE_ROOT', '1')
    server_hostname = os.environ.get("SERVER_HOSTNAME")
    if not server_hostname:
        server_hostname = '%h'

    cmd = [
        'celery', 'worker',
        '-A', 'celery_api',
        '-l', 'INFO',
        '-c', str(num),
        '-Q', queue,
        '-n', '{}@{}'.format(queue, server_hostname)
    ]
    return {"cmd": cmd, "cwd": APPS_DIR}

def get_start_flower_kwargs():
    print("\n- Start Flower as Task Monitor")
    if os.getuid() == 0:
        os.environ.setdefault('C_FORCE_ROOT', '1')

    cmd = [
        'celery', 'flower',
        '-A', 'celery_api',
        '-l', 'INFO',
        '--url_prefix=flower',
        '--auto_refresh=False',
        '--max_tasks=1000',
        '--tasks_columns=uuid,name,args,state,received,started,runtime,worker'
    ]
    return {"cmd": cmd, "cwd": APPS_DIR}

def get_start_beat_kwargs():
    print("\n- Start Beat as Periodic Task Scheduler")
    os.environ.setdefault('PYTHONOPTIMIZE', '1')
    if os.getuid() == 0:
        os.environ.setdefault('C_FORCE_ROOT', '1')

    scheduler = "django_celery_beat.schedulers:DatabaseScheduler"
    cmd = [
        'celery', 'beat',
        '-A', 'celery_api',
        '-l', 'INFO',
        '--scheduler', scheduler,
        '--max-interval', '60'
    ]
    return {"cmd": cmd, 'cwd': APPS_DIR}

processes = {}

def watch_services():
    max_retry = 3
    services_retry = defaultdict(int)
    stopped_services = {}

    def check_services():
        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        for s, p in processes.items():
            print("{} Check service status: {} -> ".format(now, s), end='')
            try:
                p.wait(timeout=1)
            except subprocess.TimeoutExpired:
                pass
            ok = is_running(s)
            if not ok:
                stopped_services[s] = ''
                print("stopped with code: {}({})".format(p.returncode, p.pid))
            else:
                print("running at {}".format(p.pid))
                stopped_services.pop(s, None)
                services_retry.pop(s, None)

    def retry_start_stopped_services():
        for s in stopped_services:
            if services_retry[s] > max_retry:
                logging.info("Service start failed, exit: ", s)
                EXIT_EVENT.set()
                break

            p = start_service(s)
            logging.info("> Find {} stopped, retry {}, {}".format(
                s, services_retry[s] + 1, p.pid)
            )
            processes[s] = p
            services_retry[s] += 1

    while not EXIT_EVENT.is_set():
        try:
            with LOCK:
                check_services()
            retry_start_stopped_services()
            time.sleep(30)
        except KeyboardInterrupt:
            print("Start stop service")
            time.sleep(1)
            break
    clean_up()

def start_service(s):
    services_kwargs = {
        "gunicorn": get_start_gunicorn_kwargs,
        "celery_ansible": get_start_celery_ansible_kwargs,
        "celery_default": get_start_celery_default_kwargs,
        "beat": get_start_beat_kwargs,
        "flower": get_start_flower_kwargs,
        "daphne": get_start_daphne_kwargs,
    }

    kwargs = services_kwargs.get(s)()
    pid_file = get_pid_file_path(s)

    if os.path.isfile(pid_file):
        os.unlink(pid_file)
    cmd = kwargs.pop('cmd')
    p = subprocess.Popen(cmd, **kwargs)
    with open(pid_file, 'w') as f:
        f.write(str(p.pid))
    return p

def start_services_and_watch(s):
    logging.info(time.ctime())
    logging.info('Kubeoperator version {}, more see https://www.kubeoperator.io')

    services_set = parse_service(s)
    for i in services_set:
        if is_running(i):
            show_service_status(i)
            continue
        p = start_service(i)
        time.sleep(2)
        processes[i] = p

    if not DAEMON:
        watch_services()
    else:
        show_service_status(s)
        context = get_daemon_context()
        with context:
            watch_services()

def get_daemon_context():
    daemon_pid_file = get_pid_file_path('jms')
    context = daemon.DaemonContext(
        pidfile=pidfile.TimeoutPIDLockFile(daemon_pid_file),
        signal_map={
            signal.SIGTERM: lambda x, y: clean_up(),
            signal.SIGHUP: 'terminate',
        },
        files_preserve=files_preserve,
        detach_process=True,
    )
    return context

def stop_service(srv, sig=15):
    services_set = parse_service(srv)
    for s in services_set:
        if not is_running(s):
            show_service_status(s)
            continue
        print("Stop service: {}".format(s), end='')
        pid = get_pid(s)
        os.kill(pid, sig)
        with LOCK:
            process = processes.pop(s, None)
        if process is None:
            try:
                process = psutil.Process(pid)
            except:
                pass
        if process is None:
            print("\033[31m No process found\033[0m")
            continue
        try:
            process.wait(1)
        except:
            pass
        for i in range(STOP_TIMEOUT):
            if i == STOP_TIMEOUT - 1:
                print("\033[31m Error\033[0m")
            if not is_running(s):
                print("\033[32m Ok\033[0m")
                break
            else:
                time.sleep(1)
                continue

    if srv == "all":
        stop_daemon_service()

def stop_daemon_service():
    pid = get_pid('jms')
    if pid and check_pid(pid):
        os.kill(pid, 15)

def stop_multi_services(services):
    for s in services:
        stop_service(s, sig=9)

def stop_service_force(s):
    stop_service(s, sig=9)

def clean_up():
    if not EXIT_EVENT.is_set():
        EXIT_EVENT.set()
    processes_dump = {k: v for k, v in processes.items()}
    for s1, p1 in processes_dump.items():
        stop_service(s1)
        p1.wait()

def show_service_status(s):
    services_set = parse_service(s)
    for ns in services_set:
        if is_running(ns):
            pid = get_pid(ns)
            print("{} is running: {}".format(ns, pid))
        else:
            print("{} is stopped".format(ns))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description="""
        Kubeoperator service control tools;
        Example: \r\n
        %(prog)s start all -d;
        """
    )
    parser.add_argument(
        'action', type=str,
        choices=("start", "stop", "restart", "status"),
        help="Action to run"
    )
    parser.add_argument(
        "service", type=str, default="all", nargs="?",
        choices=("all", "web", "task", "gunicorn", "celery", "beat", "celery,beat", "flower", "ws"),
        help="The service to start",
    )
    parser.add_argument('-d', '--daemon', nargs="?", const=1)
    parser.add_argument('-w', '--worker', type=int, nargs="?", const=4)
    parser.add_argument('-f', '--force', nargs="?", const=1)
    args = parser.parse_args()
    if args.daemon:
        DAEMON = True

    if args.worker:
        WORKERS = args.worker

    action = args.action
    srv = args.service

    if action == "start":
        start_services_and_watch(srv)
        os._exit(0)
    elif action == "stop":
        print("Stop service")
        if args.force:
            stop_service_force(srv)
        else:
            stop_service(srv)
    elif action == "restart":
        DAEMON = True
        stop_service(srv)
        time.sleep(5)
        start_services_and_watch(srv)
    else:
        show_service_status(srv)


"""
Collection of sorting algorithms.
"""

def insertion(arr, inplace=False):
    """Returns arr sorted."""
    if len(arr) == 0:
        raise ValueError('Can not sort empty array')

    if not inplace:
        arr = arr.copy()

    for key in range(len(arr)):
        i = key
        while i >= 1:
            if arr[i - 1] > arr[i]:
                arr[i - 1], arr[i] = arr[i], arr[i - 1]
            else:
                break
            i -= 1
    return arr

def bubble(arr, inplace=False):
    """Returns arr sorted."""
    if len(arr) == 0:
        raise ValueError('Can not sort empty array')

    if not inplace:
        arr = arr.copy()
    sorted = False
    while not sorted:
        sorted = True
        for i in range(0, len(arr) - 1):
            if arr[i] > arr[i + 1]:
                arr[i], arr[i + 1] = arr[i + 1], arr[i]
                sorted = False
    return arr

def merge(arr):
    """Returns arr sorted. Note that inplace keyword is not available. There
    exists an inplace version of mergesort which may be implemented in the
    future."""

    if len(arr) == 0:
        raise ValueError('Can not sort empty array')

    def mergestep(arr1, arr2):
        """Returns a sorted array from combining two sorted
        arrays(arr1 & arr2).
        """
        arr1.append(float('Inf'))
        arr2.append(float('Inf'))

        p = 0
        q = 0
        k = 0
        result = []

        while p < len(arr1) - 1 or q < len(arr2) - 1:
            if arr1[p] <= arr2[q]:
                result.append(arr1[p])
                p += 1
            else:
                result.append(arr2[q])
                q += 1

        return result

    def inner_merge(arr):
        n = len(arr)
        if n == 1:
            return arr
        else:
            arr_l = inner_merge(arr[:n // 2])
            arr_r = inner_merge(arr[n // 2:])
            return mergestep(arr_l, arr_r)

    return inner_merge(arr)

def quick(arr, p=None, r=None, inplace=False):
    """Returns arr sorted."""
    if len(arr) == 0:
        raise ValueError('Can not sort empty array')

    if not inplace:
        arr = arr.copy()

    if p == None:
        p = 0
    if r == None:
        r = len(arr) - 1

    def inner_quick(arr, p, r):
        if p < r:
            arr, q = partition(arr, p, r)
            arr = inner_quick(arr, p, q - 1)
            arr = inner_quick(arr, q + 1, r)
        return arr

    def partition(arr, p, r):
        """Partitions arr from index p to index r and returns
        partitioned arr and new location of pivot q. The pivot is
        the last element of the initial input arr."""

        x = arr[r]  # select end as pivot
        i = p  # keeps track of the index of element to be swapped next.
        for j in range(p, r):
            if arr[j] < x:
                arr[i], arr[j] = arr[j], arr[i]
                i += 1
        arr[i], arr[r] = arr[r], arr[i]

        return arr, i

    return inner_quick(arr, p, r)

def heap(arr, inplace=False):
    """Returns arr sorted."""
    if len(arr) == 0:
        raise ValueError('Can not sort empty array')
    if not inplace:
        arr = arr.copy()

    def max_heapify(arr, i, heap_size):
        """Returns a max heap at root i where it is assumed that left
        and right child subtrees are assumed to be max heaps initially.
        """
        l = 2 * (i + 1) - 1  # index of left child
        r = 2 * (i + 1)  # index of right child

        # find largest value among values with indices i, l, and r
        if l < heap_size and arr[l] > arr[i]:
            largest = l
        else:
            largest = i
        if r < heap_size and arr[r] > arr[largest]:
            largest = r

        if largest != i:
            arr[largest], arr[i] = arr[i], arr[largest]
            arr = max_heapify(arr, largest, heap_size)
        return arr

    def build_max_heap(arr):
        heap_size = len(arr)
        # i goes from heap_size//2 to 0
        for i in range(heap_size // 2, -1, -1):
            arr = max_heapify(arr, i, heap_size)
        return arr

    arr = build_max_heap(arr)
    # i goes from (len(arr) - 1) to 0
    for i in range(len(arr) - 1, -1, -1):
        arr[0], arr[i] = arr[i], arr[0]
        arr = max_heapify(arr, 0, i)
    return arr


#! -*- coding: utf8 -*-

import time
from workers.facebook import FacebookCollector

class Collector(FacebookCollector) :
	def __init__(self, device_config, red_config) :
		super().__init__(device_config, red_config, 'ict://facebook/users/*')
		self.base_fields = 'id,link,name,fan_count,picture,is_verified'
		#self.user_fields = 'id,link,name,friends.summary(1),picture,is_verified,feed.summary(1).since(%d){id,type,message,permalink_url,created_time,updated_time,shares,likes.summary(1),comments.since(%d).limit(100).summary(1)}'

	def get_data(self, task_info) :
		self.uid = task_info['uid']
		if 'id' in task_info :
			self.cache_user(self.uid,None,int(task_info['id']))
		self.since = int(time.time()-30*24*3600)
		resp = self.user_get(self.uid, {'fields': self.base_fields})

		return resp

	def user_get(self, endpoint, params):
		if params is None :
			params = dict()
		if 'access_token' not in params : params['access_token'] = self.scan_access('facebook')
		uri = self.build_uri(self.api_host, endpoint, params)

		resp = self.http_get(uri, True)
		if resp is None or resp.status_code == 400 :
			resp = self.http_get(uri.replace(',fan_count,',',friends,'))

		if resp is None :
			return None
		else :
			return resp.json()

	def parse_data(self, data) :
		if data is None :
			return None

		feed = None
		if 'feed' in data :
			feed = data['feed']
		else :
			feed_uri = self.build_uri(self.api_host, self.uid+'/feed', {
				'since': self.since,
				'fields': 'id,type,message,permalink_url,created_time,updated_time,shares,likes.summary(1),comments.since(%d).limit(100).summary(1)'%(self.since),
				'access_token': self.access_token
			})
			feedr = self.http_get(feed_uri)
			try :
				feed = feedr.json()
				feed = feed['data']
			except: pass

		if feed is not None :
			for m in feed :
				self.instance_media(m, self.uid)
		user_data = self.instance_user(data)

		#print(user_data)
		return user_data

if __name__ == '__main__' :
	import sys

	DEVICE_CONFIGURE = sys.argv[1] if 1<len(sys.argv) and 1<len(sys.argv[1]) else '.collector.json'
	REDIS_CONFIGURE = sys.argv[2] if 2<len(sys.argv) and 1<len(sys.argv[2]) else 'redis.json'
	c = Collector(DEVICE_CONFIGURE, REDIS_CONFIGURE)
	c.daemon()


'''
Files to modify :
1. common_config : add our custom_dataset
2. MyPath : add path to dataset
3. create  new config files
4. create new datalaoder

'''

#creating a custom dataloader
"""
This code is based on the Torchvision repository, which was licensed under the BSD 3-Clause.
"""
import os
import pickle
import sys
import numpy as np
import torch
from PIL import Image
from torch.utils.data import Dataset
from torchvision.datasets.utils import check_integrity, download_and_extract_archive
import pandas as pd

class EuroSat(Dataset):

    def __init__(self, root, train=True, transform=None):

        super(EuroSat, self).__init__()

        self.root = root

        self.transform = transform

        self.train = train

        self.classes = ['Forest','SeaLake','PermanentCrop','Industrial','River','AnnualCrop','HerbaceousVegetation','Residential','Highway','Pasture']

        self.df = EuroSat.get_data_dict(self.root)

        #keep 75 for training and

        if train:
          self.df = self.df[self.df.train == 1.0].reset_index(drop = True)
        else:
          self.df = self.df[self.df.train == 0.0].reset_index(drop = True)

    @staticmethod
    def get_data_dict(data_dir):

        data_dict = {'path': [], 'label': []}

        for (_, labels, _) in os.walk(data_dir):
            for label in labels:
                label_dir = data_dir + label + '/'
                for (_, _, files) in os.walk(label_dir):
                    for file in files:
                        data_dict['path'].append(label_dir + file)
                        data_dict['label'].append(label)

        df =  pd.DataFrame(data_dict)
        #shuffling the dataframe.
        df = df.sample(frac=1).reset_index(drop=True)

        n = len(df)
        #set 75 for training and   and 25 for testing

        df['train'] = np.zeros(n)

        df.loc[0:int(n * 0.75),'train'] = 1

        return df

    def __getitem__(self, index):
        """
        Args:
            index (int): Index
        Returns:
            dict: {'image': image, 'target': index of target class, 'meta': dict}
        """
        img = self.get_image(index)
        img_size = img.size

        class_name = self.df['label'][index]
        target = self.classes.index(class_name)

        if self.transform is not None:
            img = self.transform(img)

        out = {'image': img, 'target': target, 'meta': {'im_size': img_size, 'index': index, 'class_name': class_name}}

        return out

    def get_image(self, index):
        img_path = self.df['path'][index]
        img = Image.open(img_path)
        return img

    #functions used for plotting images
    def show_img(self,index):
        img =  self.get_image(index)
        plt.imshow(img)

    # will create a batch x batch images
    def plot_batch(self,batch = 8):
        n_images = len(self.df)

        indices = np.random.choice(range(n_images) , size= batch **2)

        #creating an image array
        labels = self.df['label'][indices].reset_index(drop = True)
        images = [np.array(self.get_image(i)) for i in indices]

        fig,axis = plt.subplots(batch,batch,figsize = (20,20))

        for i,ax in enumerate(axis.flatten()):

            ax.imshow(images[i])
            ax.set_title(labels[i])
            ax.xaxis.set_visible(False)
            ax.yaxis.set_visible(False)

    def __len__(self):
        return len(self.df)