from re import compile as re_compile
from random import shuffle
from os import path as os_path, listdir, stat
from time import localtime
from enigma import RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eServiceReference, eServiceCenter, gFont
from Components.MenuList import MenuList
from Components.Harddisk import harddiskmanager
from Tools.Directories import SCOPE_CURRENT_SKIN, resolveFilename, pathExists, fileExists
from Tools.LoadPixmap import LoadPixmap
EXTENSIONS = {
		"m4a": "music",
		"mp2": "music",
		"mp3": "music",
		"wma": "music",
		"wav": "music",
		"ogg": "music",
		"m3u": "music",
		"flac": "music",
		"jpg": "picture",
		"jpeg": "picture",
		"png": "picture",
		"bmp": "picture",
		"mts": "movie",
		"m2ts": "movie",
		"pls": "music",
		"vdr": "movie",
		"vob": "movie",
		"ogm": "movie",
		"wmv": "movie",
		"ts": "movie",
		"avi": "movie",
		"divx": "movie",
		"mpg": "movie",
		"mpeg": "movie",
		"mkv": "movie",
		"mp4": "movie",
		"mov": "movie",
		"trp": "movie",
		"m4v": "movie",
		"flv": "movie",
		"rar": "rar",
		"iso": "iso",
		"img": "img"
	}

def FileEntryComponent(name, absolute=None, isDir=False, directory="/", size=0, timestamp=0):
	res = [(absolute, isDir, name)]
	if name == "..":
		res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 1000, 20, 0, RT_HALIGN_LEFT, name))
	else:
		res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 1000, 20, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, name))
	#res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 470, 20, 0, RT_HALIGN_LEFT, name))
	if isDir:
		png = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "extensions/directory.png"))
	else:
		extension = name.split('.')
		extension = extension[-1].lower()
		if extension in EXTENSIONS:
			png = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "extensions/" + EXTENSIONS[extension] + ".png"))
		else:
			png = None
	if png is not None:
		res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
	return res

class FileList(MenuList):
	def __init__(self, directory, showDirectories=True, showFiles=True, showMountpoints=True, matchingPattern=None, useServiceRef=False, inhibitDirs=False, inhibitMounts=False, isTop=False, enableWrapAround=False, additionalExtensions=None, sort="default"):
		MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
		self.additional_extensions = additionalExtensions
		self.mountpoints = []
		self.current_directory = None
		self.current_mountpoint = None
		self.useServiceRef = useServiceRef
		self.showDirectories = showDirectories
		self.showMountpoints = showMountpoints
		self.showFiles = showFiles
		self.isTop = isTop
		# example: matching .nfi and .ts files: "^.*\.(nfi|ts)"
		self.matchingPattern = matchingPattern
		self.sort = sort
		self.inhibitDirs = inhibitDirs or []
		self.inhibitMounts = inhibitMounts or []
		self.refreshMountpoints()
		self.changeDir(directory, sort=sort)
		self.l.setFont(0, gFont("Regular", 18))
		self.l.setItemHeight(21)
		self.serviceHandler = eServiceCenter.getInstance()

	def refreshMountpoints(self):
		self.mountpoints = [os_path.join(p.mountpoint, "") for p in harddiskmanager.getMountedPartitions()]
		self.mountpoints.sort(reverse=True)

	def getMountpoint(self, file):
		file = os_path.join(os_path.realpath(file), "")
		for m in self.mountpoints:
			if file.startswith(m):
				return m
		return False

	def getMountpointLink(self, file):
		if os_path.realpath(file) == file:
			return self.getMountpoint(file)
		else:
			if file[-1] == "/":
				file = file[:-1]
			mp = self.getMountpoint(file)
			last = file
			file = os_path.dirname(file)
			while last != "/" and mp == self.getMountpoint(file):
				last = file
				file = os_path.dirname(file)
			return os_path.join(last, "")

	def getSelection(self):
		if self.l.getCurrentSelection() is None:
			return None
		return self.l.getCurrentSelection()[0]

	def getCurrentEvent(self):
		l = self.l.getCurrentSelection()
		if not l or l[0][1] == True:
			return None
		else:
			return self.serviceHandler.info(l[0][0]).getEvent(l[0][0])

	def getFileList(self):
		return self.list

	def inParentDirs(self, dir, parents):
		dir = os_path.realpath(dir)
		for p in parents:
			if dir.startswith(p):
				return True
		return False

	def changeDir(self, directory, sort="default", select=None):
		isDir = False
		if sort == "shuffle":
			sort = "default"
			shuffleplay = True
		else:
			shuffleplay = False
		self.list = []
		if self.current_directory is None:
			if directory and self.showMountpoints:
				self.current_mountpoint = self.getMountpointLink(directory)
			else:
				self.current_mountpoint = None
		self.current_directory = directory
		directories = []
		files = []
		if directory is None and self.showMountpoints:
			for p in harddiskmanager.getMountedPartitions():
				path = os_path.join(p.mountpoint, "")
				if path not in self.inhibitMounts and not self.inParentDirs(path, self.inhibitDirs):
					self.list.append(FileEntryComponent(name=p.description, absolute=path, isDir=True, directory=directory))
			files = []
			directories = []
		elif directory is None:
			files = []
			directories = []
		elif self.useServiceRef:
			root = eServiceReference(2, 0, directory)
			if self.additional_extensions:
				root.setName(self.additional_extensions)
			serviceHandler = eServiceCenter.getInstance()
			list = serviceHandler.list(root)
			while True:
				s = list.getNext()
				if not s.valid():
					del list
					break
				if s.flags & s.mustDescent:
					directories.append(s.getPath())
				else:
					files.append(s)
			directories.sort()
			files.sort()
		else:
			if fileExists(directory):
				try:
					files = listdir(directory)
				except:
					files = []
				files.sort()
				tmpfiles = files[:]
				for x in tmpfiles:
					if os_path.isdir(directory + x):
						directories.append(directory + x + "/")
						files.remove(x)
		if directory is not None and self.showDirectories and not self.isTop:
			if directory == self.current_mountpoint and self.showMountpoints:
				self.list.append(FileEntryComponent(name="<" + _("List of storage Devices") + ">", absolute=None, isDir=True, directory=directory))
			elif (directory != "/") and not (self.inhibitMounts and self.getMountpoint(directory) in self.inhibitMounts):
				self.list.append(FileEntryComponent(name="<" + _("Parent directory") + ">", absolute='/'.join(directory.split('/')[:-2]) + '/', isDir=True, directory=directory))
		date_file_list = []
		if self.showDirectories:
			for x in directories:
				if not (self.inhibitMounts and self.getMountpoint(x) in self.inhibitMounts) and not self.inParentDirs(x, self.inhibitDirs):
					name = x.split('/')[-2]
					file = x
					path = x
					if pathExists(path):
						stats = stat(path)
						size = stats[6]
						lastmod_date = localtime(stats[8])
					else:
						size = 0
						lastmod_date = 0
					isDir = True
					if sort == "size" or sort == "sizereverse":
						date_file_tuple = size, name, path, file, lastmod_date, isDir
					elif sort == "date" or sort == "datereverse" or sort == "default":
						date_file_tuple = lastmod_date, name, path, file, size, isDir
					elif sort == "alpha" or sort == "alphareverse":
						date_file_tuple = name, lastmod_date, path, file, size, isDir
					date_file_list.append(date_file_tuple)
		if self.showFiles:
			for x in files:
				if self.useServiceRef:
					path = x.getPath()
					name = path.split('/')[-1]
					file = x
					if pathExists(path):
						stats = stat(path)
						size = stats[6]
						lastmod_date = localtime(stats[8])
					else:
						size = 0
						lastmod_date = 0
					isDir = False
					if sort == "size" or sort == "sizereverse":
						date_file_tuple = size, name, path, file, lastmod_date, isDir
					elif sort == "date" or sort == "datereverse" or sort == "default":
						date_file_tuple = lastmod_date, name, path, file, size, isDir
					elif sort == "alpha" or sort == "alphareverse":
						date_file_tuple = name, lastmod_date, path, file, size, isDir
					date_file_list.append(date_file_tuple)
				else:
					path = directory + x
					name = x
					if sort == "size" or sort == "sizereverse":
						date_file_tuple = size, name, path, file, lastmod_date, isDir
					elif sort == "date" or sort == "datereverse" or sort == "default":
						date_file_tuple = lastmod_date, name, path, file, size, isDir
					elif sort == "alpha" or sort == "alphareverse":
						date_file_tuple = name, lastmod_date, path, file, size, isDir
					date_file_list.append(date_file_tuple)
		if sort == "datereverse" or sort == "alpha" or sort == "sizereverse" or sort == "date" or sort == "alphareverse" or sort == "size":
			date_file_list.sort()
		if sort == "date" or sort == "alphareverse" or sort == "size":
			date_file_list.reverse()
		if shuffleplay == True:
			shuffle(date_file_list)
		for x in date_file_list:
			if sort == "size" or sort == "sizereverse":
				size = x[0]
				name = x[1]
				path = x[2]
				file = x[3]
				timestamp = x[4]
				isDir = x[5]
			elif sort == "date" or sort == "datereverse" or sort == "default":
				timestamp = x[0]
				name = x[1]
				path = x[2]
				file = x[3]
				size = x[4]
				isDir = x[5]
			elif sort == "alpha" or sort == "alphareverse":
				name = x[0]
				timestamp = x[1]
				path = x[2]
				file = x[3]
				size = x[4]
				isDir = x[5]
			if isDir == True:
				if not (self.inhibitMounts and self.getMountpoint(file) in self.inhibitMounts) and not self.inParentDirs(file, self.inhibitDirs):
					self.list.append(FileEntryComponent(name=name, absolute=file, isDir=isDir, directory=directory, size=size, timestamp=timestamp))
			else:
				if (self.matchingPattern is None) or re_compile(self.matchingPattern).search(path):
					self.list.append(FileEntryComponent(name=name, absolute=file, isDir=isDir, directory=directory, size=size, timestamp=timestamp))
		if self.showMountpoints and len(self.list) == 0:
			self.list.append(FileEntryComponent(name=_("nothing connected"), absolute=None, isDir=False))
		self.l.setList(self.list)
		if select is not None:
			i = 0
			self.moveToIndex(0)
			for x in self.list:
				p = x[0][0]
				if isinstance(p, eServiceReference):
					p = p.getPath()
				if p == select:
					self.moveToIndex(i)
				i += 1

	def getCurrentDirectory(self):
		return self.current_directory

	def canDescent(self):
		if self.getSelection() is None:
			return False
		return self.getSelection()[1]

	def descent(self):
		if self.getSelection() is None:
			return
		self.changeDir(self.getSelection()[0], select=self.current_directory)

	def gotoParent(self):
		if self.current_directory is not None:
			if self.current_directory == self.current_mountpoint and self.showMountpoints:
				absolute = None
			else:
				absolute = '/'.join(self.current_directory.split('/')[:-2]) + '/'
			self.changeDir(absolute, select=self.current_directory)

	def getName(self):
		if self.getSelection() is None:
			return False
		return self.getSelection()[2]

	def getFilename(self):
		if self.getSelection() is None:
			return None
		x = self.getSelection()[0]
		if isinstance(x, eServiceReference):
			x = x.getPath()
		return x

	def getServiceRef(self):
		if self.getSelection() is None:
			return None
		x = self.getSelection()[0]
		if isinstance(x, eServiceReference):
			return x
		return None

	def execBegin(self):
		harddiskmanager.on_partition_list_change.append(self.partitionListChanged)

	def execEnd(self):
		harddiskmanager.on_partition_list_change.remove(self.partitionListChanged)

	def refresh(self, sort="default"):
		self.sort = sort
		self.changeDir(self.current_directory, self.sort, self.getFilename())

	def partitionListChanged(self, action, device):
		self.refreshMountpoints()
		if self.current_directory is None:
			self.refresh()

def MultiFileSelectEntryComponent(name, absolute=None, isDir=False, selected=False):
	res = [(absolute, isDir, selected, name)]
	res.append((eListboxPythonMultiContent.TYPE_TEXT, 55, 1, 470, 20, 0, RT_HALIGN_LEFT, name))
	if isDir:
		png = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "extensions/directory.png"))
	else:
		extension = name.split('.')
		extension = extension[-1].lower()
		if extension in EXTENSIONS:
			png = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "extensions/" + EXTENSIONS[extension] + ".png"))
		else:
			png = None
	if png is not None:
		res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 30, 2, 20, 20, png))
	if not name.startswith('<'):
		if selected is False:
			icon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_off.png"))
			res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 2, 0, 25, 25, icon))
		else:
			icon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_on.png"))
			res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 2, 0, 25, 25, icon))
	return res

class MultiFileSelectList(FileList):
	def __init__(self, preselectedFiles, directory, showMountpoints=False, matchingPattern=None, showDirectories=True, showFiles=True, useServiceRef=False, inhibitDirs=False, inhibitMounts=False, isTop=False, enableWrapAround=False, additionalExtensions=None):
		self.selectedFiles = preselectedFiles
		if self.selectedFiles is None:
			self.selectedFiles = []
		FileList.__init__(self, directory, showMountpoints=showMountpoints, matchingPattern=matchingPattern, showDirectories=showDirectories, showFiles=showFiles, useServiceRef=useServiceRef, inhibitDirs=inhibitDirs, inhibitMounts=inhibitMounts, isTop=isTop, enableWrapAround=enableWrapAround, additionalExtensions=additionalExtensions)
		self.changeDir(directory)
		self.l.setItemHeight(25)
		self.l.setFont(0, gFont("Regular", 20))
		self.onSelectionChanged = []

	def selectionChanged(self):
		for f in self.onSelectionChanged:
			f()

	def changeSelectionState(self):
		idx = self.l.getCurrentSelectionIndex()
		count = 0
		newList = []
		for x in self.list:
			if idx == count:
				if x[0][3].startswith('<'):
					newList.append(x)
				else:
					if x[0][1] is True:
						realPathname = x[0][0]
					else:
						realPathname = self.current_directory + x[0][0]
					if x[0][2] == True:
						SelectState = False
						for entry in self.selectedFiles:
							if entry == realPathname:
								self.selectedFiles.remove(entry)
					else:
						SelectState = True
						alreadyinList = False
						for entry in self.selectedFiles:
							if entry == realPathname:
								alreadyinList = True
						if not alreadyinList:
							self.selectedFiles.append(realPathname)
					newList.append(MultiFileSelectEntryComponent(name=x[0][3], absolute=x[0][0], isDir=x[0][1], selected=SelectState))
			else:
				newList.append(x)
			count += 1
		self.list = newList
		self.l.setList(self.list)

	def getSelectedList(self):
		return self.selectedFiles

	def changeDir(self, directory, select=None):
		self.list = []
		# if we are just entering from the list of mount points:
		if self.current_directory is None:
			if directory and self.showMountpoints:
				self.current_mountpoint = self.getMountpointLink(directory)
			else:
				self.current_mountpoint = None
		self.current_directory = directory
		directories = []
		files = []
		if directory is None and self.showMountpoints:  # present available mountpoints
			for p in harddiskmanager.getMountedPartitions():
				path = os_path.join(p.mountpoint, "")
				if path not in self.inhibitMounts and not self.inParentDirs(path, self.inhibitDirs):
					self.list.append(MultiFileSelectEntryComponent(name=p.description, absolute=path, isDir=True))
			files = []
			directories = []
		elif directory is None:
			files = []
			directories = []
		elif self.useServiceRef:
			root = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + directory)
			if self.additional_extensions:
				root.setName(self.additional_extensions)
			serviceHandler = eServiceCenter.getInstance()
			list = serviceHandler.list(root)
			while True:
				s = list.getNext()
				if not s.valid():
					del list
					break
				if s.flags & s.mustDescent:
					directories.append(s.getPath())
				else:
					files.append(s)
			directories.sort()
			files.sort()
		else:
			if fileExists(directory):
				try:
					files = listdir(directory)
				except:
					files = []
				files.sort()
				tmpfiles = files[:]
				for x in tmpfiles:
					if os_path.isdir(directory + x):
						directories.append(directory + x + "/")
						files.remove(x)
		if directory is not None and self.showDirectories and not self.isTop:
			if directory == self.current_mountpoint and self.showMountpoints:
				self.list.append(MultiFileSelectEntryComponent(name="<" + _("List of Storage Devices") + ">", absolute=None, isDir=True))
			elif (directory != "/") and not (self.inhibitMounts and self.getMountpoint(directory) in self.inhibitMounts):
				self.list.append(MultiFileSelectEntryComponent(name="<" + _("Parent Directory") + ">", absolute='/'.join(directory.split('/')[:-2]) + '/', isDir=True))
		if self.showDirectories:
			for x in directories:
				if not (self.inhibitMounts and self.getMountpoint(x) in self.inhibitMounts) and not self.inParentDirs(x, self.inhibitDirs):
					name = x.split('/')[-2]
					alreadySelected = False
					for entry in self.selectedFiles:
						if entry == x:
							alreadySelected = True
					if alreadySelected:
						self.list.append(MultiFileSelectEntryComponent(name=name, absolute=x, isDir=True, selected=True))
					else:
						self.list.append(MultiFileSelectEntryComponent(name=name, absolute=x, isDir=True, selected=False))
		if self.showFiles:
			for x in files:
				if self.useServiceRef:
					path = x.getPath()
					name = path.split('/')[-1]
				else:
					path = directory + x
					name = x
				if (self.matchingPattern is None) or re_compile(self.matchingPattern).search(path):
					alreadySelected = False
					for entry in self.selectedFiles:
						if os_path.basename(entry) == x:
							alreadySelected = True
					if alreadySelected:
						self.list.append(MultiFileSelectEntryComponent(name=name, absolute=x, isDir=False, selected=True))
					else:
						self.list.append(MultiFileSelectEntryComponent(name=name, absolute=x, isDir=False, selected=False))
		self.l.setList(self.list)
		if select is not None:
			i = 0
			self.moveToIndex(0)
			for x in self.list:
				p = x[0][0]
				if isinstance(p, eServiceReference):
					p = p.getPath()
				if p == select:
					self.moveToIndex(i)
				i += 1


import os.path as osp
import time
import pprint
import logging
import torch
import cv2
import numpy as np
from yacs.config import CfgNode as CN

from seglossbias.modeling import build_model
from seglossbias.evaluation import build_evaluator, AverageMeter
from seglossbias.data import build_data_pipeline
from seglossbias.utils import (
    get_best_model_path, get_last_model_path, mkdir
)

logger = logging.getLogger(__name__)

class DefaultTester:
    """
    A tester with default testing logic. It does the following:

    1. Create a model and init with trained weights
    2. build dataloader to generate mini-batch input data
    3. Create loss meter and performance evaluator
    4. Loop through all the dataset to evaluate and save results if required
    """
    def __init__(self, cfg: CN):
        self.cfg = cfg
        logger.info("DefaultTester with config : ")
        logger.info(pprint.pformat(self.cfg))
        self.device = torch.device(self.cfg.DEVICE)
        self.data_loader = build_data_pipeline(self.cfg, self.cfg.TEST.SPLIT)
        self.build_model()
        if self.cfg.TEST.SAVE_PREDICTS:
            self.save_path = osp.join(self.cfg.OUTPUT_DIR,
                                      "{}_results".format(self.cfg.TEST.SPLIT))
            mkdir(self.save_path)
        self.build_meter()

    def build_model(self):
        if self.cfg.TEST.CHECKPOINT_PATH:
            model_path = self.cfg.TEST.CHECKPOINT_PATH
        elif self.cfg.TEST.MODEL_EPOCH > 0:
            model_path = osp.join(
                self.cfg.OUTPUT_DIR,
                "model/checkpoint_epoch_{}.pth".format(self.cfg.TEST.MODEL_EPOCH)
            )
        elif self.cfg.TEST.BEST_CHECKPOINT:
            model_path = get_best_model_path(self.cfg)
        else:
            model_path = get_last_model_path(self.cfg)

        self.model = build_model(self.cfg, model_path=model_path)
        self.model.to(self.device)

    def build_meter(self):
        self.evaluator = build_evaluator(self.cfg)
        self.batch_time_meter = AverageMeter()

    def reset_meter(self):
        self.evaluator.reset()
        self.batch_time_meter.reset()

    def log_iter_info(self, iter, max_iter, batch_time_meter=None, score=None):
        log_str = []
        log_str.append("Test Epoch[{}/{}]".format(iter + 1, max_iter))
        if batch_time_meter is not None:
            log_str.append(
                "Time {batch_time.val:.3f} ({batch_time.avg:.3f})"
                .format(batch_time=batch_time_meter)
            )
        if score is not None:
            log_str.append("{} {:.4f}".format(self.evaluator.main_metric(), score))
        logger.info("\t".join(log_str))

    def log_epoch_info(self, evaluator):
        log_str = []
        log_str.append("Test Samples[{}]".format(evaluator.num_samples()))
        log_str.append("{} {:.4f}".format(evaluator.main_metric(), evaluator.mean_score()))
        logger.info("\t".join(log_str))

        if self.cfg.MODEL.NUM_CLASSES > 1:
            evaluator.class_score()

    def save_predicts_or_not(self, predicts, sample_ids):
        if not self.cfg.TEST.SAVE_PREDICTS:
            return

        if self.cfg.MODEL.NUM_CLASSES == 1:
            pred_labels = (predicts.squeeze(dim=1) > self.cfg.THRES).int().cpu().numpy()
        else:
            pred_labels = torch.argmax(predicts, dim=1).cpu().numpy()

        for i, sample_id in enumerate(sample_ids):
            out_image = pred_labels[i].astype(np.uint8)
            out_file = osp.join(self.save_path, sample_id + ".png")
            cv2.imwrite(out_file, out_image)

    @torch.no_grad()
    def test(self):
        self.reset_meter()
        self.model.eval()

        max_iter = len(self.data_loader)
        end = time.time()
        for i, samples in enumerate(self.data_loader):
            inputs, labels = samples[0].to(self.device), samples[1].to(self.device)
            # forward
            outputs = self.model(inputs)
            predicts = self.model.act(outputs)
            score = self.evaluator.update(predicts.detach().cpu().numpy(),
                                          labels.detach().cpu().numpy())
            # measure elapsed time
            self.batch_time_meter.update(time.time() - end)
            self.save_predicts_or_not(predicts, samples[-1])
            # logging
            if (i + 1) % self.cfg.LOG_PERIOD == 0:
                self.log_iter_info(i, max_iter,
                                   batch_time_meter=self.batch_time_meter,
                                   score=score)

            end = time.time()
        self.log_epoch_info(self.evaluator)

class ImageFolderTester(DefaultTester):
    """
    A tester for inference with a given image folder as input,
    Compared with Default Tester, it doesn't contain the evaluation but save all the output masks.
    """
    def __init__(self, cfg: CN, save_path: str):
        self.cfg = cfg
        logger.info("ImageFolderTester with config : ")
        logger.info(pprint.pformat(self.cfg))
        self.device = torch.device(self.cfg.DEVICE)
        self.data_loader = build_data_pipeline(self.cfg, self.cfg.TEST.SPLIT)
        self.build_model()
        self.save_path = save_path
        mkdir(self.save_path)

    def save_predicts(self, predicts, sample_ids):
        if self.cfg.MODEL.NUM_CLASSES == 1:
            pred_labels = (predicts.squeeze(dim=1) > self.cfg.THRES).int().cpu().numpy()
        else:
            pred_labels = torch.argmax(predicts, dim=1).cpu().numpy()

        for i, sample_id in enumerate(sample_ids):
            out_image = np.uint8(pred_labels[i] * 255)
            out_file = osp.join(self.save_path, osp.splitext(sample_id)[0] + ".png")
            cv2.imwrite(out_file, out_image)

    @torch.no_grad()
    def test(self):
        timer = AverageMeter()

        self.model.eval()
        max_iter = len(self.data_loader)
        end = time.time()
        for i, samples in enumerate(self.data_loader):
            inputs, sample_ids = samples[0].to(self.device), samples[1]
            # forward
            outputs = self.model(inputs)
            predicts = self.model.act(outputs)
            # save predicts to predicted mask image
            self.save_predicts(predicts, sample_ids)
            timer.update(time.time() - end)
            logger.info(
                "Test Epoch[{}/{}] Time {timer.val:.3f} ({timer.avg:.3f})".format(
                    i + 1, max_iter, timer=timer)
            )
            end = time.time()
        logger.info("Done with test Samples[{}]".format(len(self.data_loader.dataset)))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from flask_script import Manager, Shell
from app import create_app, db
from app.models import Post, User, Profile

app = create_app(os.environ.get('FLASK_CONFIG') or 'default')
manager = Manager(app)

def make_shell_context():
    """
    make_context的回调函数：注册了必要的程序、数据库、模型。
    在以shell模式启动manager时，这些对象可以直接导入shell。
    """
    return dict(app=app, db=db, Post=Post, User=User, Profile=Profile)
manager.add_command("shell", Shell(make_context=make_shell_context))

@manager.command
def deploy():
    """新数据库需要创建管理员用户"""
    User.insert_admin()

if __name__ == '__main__':
    manager.run()


"""
Author: Marissa Mocenigo

This class interacts with the web components

"""

import logging

from flask import Flask, render_template, request
from flask_googlemaps import GoogleMaps, Map
from source.user_location import get_user_info, get_location_data, where_am_i
from config import GOOGLE_API_KEY
from source.activity_manager import plan_hours

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize the Flask application
app = Flask(__name__)
app.config['GOOGLEMAPS_KEY'] = GOOGLE_API_KEY
GoogleMaps(app)

@app.route('/')
def index():
    user_info = get_user_info()
    return render_template('index.html', user_info=user_info)

@app.route('/suggestions', methods=['POST'])
def request_itinerary():
    hours = request.form['hours']
    location = get_location_data()
    latlong = str(location['latitude']) + "," + str(location['longitude'])
    activities = plan_hours(latlong, float(hours), [])
    if len(activities) > 0:
        markers = []# [(a["lat"], a["lng"]) for a in activities]
        for a in activities:
            m = {
             'lat': a["lat"],
             'lng': a["lng"],
             'infobox': a["name"]
          }
            markers.append(m)
        map = Map(
                identifier="view-side",
                lat=location['latitude'],
                lng=location['longitude'],
                markers=markers,
                style = "height:500px;width:100%;margin:5px;"
            )
        return render_template('suggestion.html', hours=hours, activities=activities, map=map)
    else:
        render_template('suggestion.html', hours=hours)

if __name__ == '__main__':
    app.run()


import time,re

from selenium.common.exceptions import NoSuchElementException

#### OUR LIBS, CONFIG ####
from lib.core.mobile.assertions import AppiumAssertions
from settings.ios import iOSSettings
from settings.locatorsios_v5 import Locators
from lib.tools.adUtils import AdUtils

class PlayAdsV5Assertions(AppiumAssertions):

    locators = Locators()
    settings = iOSSettings()
    ad_utils = AdUtils()

    def verifyInitAdPage(self,tester=None):
        self.setTestProcedure("function","verifyInitAdPage")
        return self.isElementDisplayedById(tester, self.locators.LOC_IOS_EXIT_ID)

    def verifyDownloadAdByPlacementId(self, tester, placement_id, placement_index, scroll=True):
        self.setTestProcedure("function", "verifyDownloadAdByPlacementId:placement_id=%s"%placement_id)
        max_retry = 15
        wait_time = 5
        found = False
        try:
            print("Placement_id=%s is processing..."%placement_id)
            status = True
            if scroll:
                status = self.scrollDownElementByIdSmart(tester,placement_id)
            found = False
            if not status:
                print("placement_id=%s not found on screen."%placement_id)
            else:
                for i in range(0,max_retry):
                    if not self.isPlacementV5Downloaded(placement_index):
                        self.setTestProcedure("debug", "Placement=%s is downloading... retry=%i/%s in %s secs."%(placement_id,i,max_retry,wait_time))
                        time.sleep(wait_time)
                        found = False
                        if i >= 3:
                            self.setTestProcedure("debug", "Switch to Log tab then back again to reload page")
                            self.driver.find_element_by_id(self.locators.LOC_IOS_LOGS_TAB_BAR_ID).click()
                            time.sleep(1)
                            self.driver.find_element_by_xpath(self.locators.LOC_IOS_VUNGLE_TAB_BAR_XPATH).click()
                            time.sleep(1)
                            self.scrollDownElementByIdSmart(tester,placement_id)
                    else:
                        print("Placement_id=%s has been downloaded. Ready to play."%placement_id)
                        found = True
                        break
                if i >= max_retry-1 and found == False:
                    self.setTestProcedure("fail","Placement_id=%s is failed to download."%placement_id)
                    self.takeScreenshot("test", self.settings.REPORT_LOCATION+"/"+self.removeSpecialChars(str(tester)))
                    return False
        except Exception as err:
            self.setTestProcedure("error","Placement ID=%s error because of %s"%(placement_id,str(err)))
            self.takeScreenshot("test", self.settings.REPORT_LOCATION+"/"+self.removeSpecialChars(str(tester)))
            return False
        return found

    def isPlacementV5Downloaded(self, placement_index):
        self.setTestProcedure("function", "isPlacementV5Downloaded")
        try:
            element_value = self.driver.find_element_by_xpath("%s[%s]//XCUIElementTypeButton[3]"%(self.locators.LOC_IOS_PLACEMENT_XPATH,str(placement_index))).get_attribute("value")
            print("Current status is %s"%element_value)
            if element_value is None:
                return False
            elif int(element_value) == 1:  # already download
                return True
            return False
        except NoSuchElementException as err:
            print(err.args)

    def verifyImage(self,tester,file_expected,file_actual,ratio_expected=50):
        self.setTestProcedure("function", "verifyImage")
        'compare file_actual with golden image from test'
        self.setTestProcedure("function", "verifyImage:file_exepected=%s"%file_expected)
        self.setTestProcedure("debug", "file_actual=%s"%file_actual)
        ratio_actual = self.ad_utils.compareImage(tester,file_expected,file_actual)
        self.setTestProcedure('debug',"ratio_actual=%s"%ratio_actual)
        if ratio_actual <= ratio_expected:
            tester.assertTrue(True,"Actual=%s and expected=%s size are IN the expected range."%(ratio_actual,ratio_expected))
        else:
            tester.assertFalse(ratio_actual > ratio_expected ,"Actual=%s is greater than the expected=%s size range."%(ratio_actual,ratio_expected))

    def isIncentivizedPopupDisplayed(self, tester):
        self.setTestProcedure("function", "isIncentivizedPopupDisplay")
        return self.isElementDisplayedByXpath(tester, self.locators.LOC_IOS_PLAY_REWARD_AD_INCENTIVIZED_POPUP_XPATH)

    def isFlexfeedAdDimensionCorrect(self, tester, expected_width, expected_height):
        self.setTestProcedure("function", "isFlexfeedAdDimensionCorrect")
        size = self.driver.find_element_by_xpath(self.locators.LOC_IOS_PLAY_FLEXFEED_AD_XPATH).size
        print("size = %s" %size)
        actual_width = int(size["width"])
        actual_height = int(size["height"])
        return actual_width==expected_width and actual_height==expected_height

    def isFlexViewAdDisplay(self, tester):
        self.setTestProcedure("function","isFlexViewAdDisplay")
        return self.isElementDisplayedByXpath(tester, self.locators.LOC_IOS_PLAY_FLEXVIEW_AD_XPATH)


import base64
import hashlib
import hmac
import datetime
import json
import requests

class LogAnalytics:
    def __init__(self, workspace_id, workspace_key, log_type):
        self.workspace_id = workspace_id
        self.workspace_key = workspace_key
        self.log_type = log_type

    # Azure Provided Code for posting data to Azure Log Ingestion
    def build_signature(self, date, content_length, method, content_type, resource):
        x_headers = 'x-ms-date:' + date
        string_to_hash = (
            method
            + "\n"
            + str(content_length)
            + "\n"
            + content_type
            + "\n"
            + x_headers
            + "\n"
            + resource
        )
        bytes_to_hash = bytes(string_to_hash, encoding='utf-8')
        decoded_key = base64.b64decode(self.workspace_key)
        encoded_hash = base64.b64encode(
            hmac.new(decoded_key, bytes_to_hash, digestmod=hashlib.sha256).digest()
        ).decode()
        authorization = "SharedKey {}:{}".format(self.workspace_id, encoded_hash)
        return authorization

    # Required Function to create and invoke an API POST request to the Azure Log Analytics Data Collector API. Reference: https://docs.microsoft.com/azure/azure-functions/functions-reference-python#environment-variables
    def post_data(self, data):
        body = json.dumps(data, sort_keys=True)
        method = 'POST'
        content_type = 'application/json'
        resource = '/api/logs'
        rfc1123date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
        content_length = len(body)
        signature = self.build_signature(
            rfc1123date,
            content_length,
            method,
            content_type,
            resource,
        )
        uri = f'https://{self.workspace_id}.ods.opinsights.azure.com{resource}?api-version=2016-04-01'

        headers = {
            'content-type': content_type,
            'Authorization': signature,
            'Log-Type': self.log_type,
            'x-ms-date': rfc1123date,
        }

        response = requests.post(uri, data=body, headers=headers)
        response.raise_for_status()