# Path: ipet/parsing/StatisticReader.py
# class StatisticReader(IpetNode):
#     """
#     base class for all statistic readers - readers should always inherit from this base class for minimal implementation
#     effort
# 
#     readers only need to overwrite the methods extractStatistic() and perhaps execEndOfProb()
#     """
# 
#     name = 'NO_NAME_DEFINED_YET'
#     regular_exp = re.compile('')
#     datakey = 'NO KEY'
#     datatype = float
#     lineindex = -1
# 
#     context = Key.CONTEXT_LOGFILE
# 
#     sleepAfterReturn = True
#     sleep = False
# 
#     multipliers = dict(k=1000, M=1e6, G=1e9)
# 
#     # the reader might behave differently depending on the solver type, due to the different output
#     SOLVERTYPE_SCIP = "SCIP"
#     SOLVERTYPE_GUROBI = "GUROBI"
#     SOLVERTYPE_CPLEX = "CPLEX"
#     SOLVERTYPE_CBC = "CBC"
#     SOLVERTYPE_XPRESS = "XPRESS"
#     SOLVERTYPE_COUENNE = "Couenne"
#     solvertype = SOLVERTYPE_SCIP
# 
#     @staticmethod
#     def boolfunction(value):
#         """ parses string TRUE or FALSE and returns the boolean value of this expression """
#         return True if value == "TRUE" else False
# 
#     @staticmethod
#     def changeSolverType(newtype):
#         StatisticReader.solvertype = newtype
# 
#     def setTestRun(self, testrun):
#         self.testrun = testrun
# 
#     def supportsContext(self, context):
#         """
#         returns True if the reader supports a given context, otherwise False
#         """
#         if type(self.context) is int:
#             return self.context == context
#         else:
#             return context in self.context
# 
#     def getSplitLineWithRegexp(self, regular_exp, line, index=-1, startofline=False):
#         if startofline == True and not re.match(regular_exp, line):
#             return None
#         if startofline == False and not re.search(regular_exp, line):
#             return None
# 
#         if index == -1:
#             return line.split()
#         else:
#             return line.split()[index]
# 
#     def getName(self):
#         """
#         returns the name of the StatisticReader
#         """
#         return self.name
# 
#     def extractStatistic(self, line):
#         """
#         overwrite this method for own reader subclasses
#         """
#         try:
#             if self.regular_exp.search(line):
#                 data = None
#                 try:
#                     data = self.datatype(misc.getWordAtIndex(line, self.lineindex))
#                 except ValueError:
#                     data = None
#                 except IndexError:
#                     data = None
#                 except TypeError:
# #                  print self.name, " failed data conversion"
#                     raise TypeError("Type error during data conversion in line <%s>" % line)
#                 self.addData(self.datakey, data)
#         except AttributeError:
# #          print self.name, " has no such attribute"
#             pass
# 
#     def execEndOfProb(self):
#         """
#         overwrite this method to implement final behaviour at the end of each problem, such as setting flags
#         """
#         return None
# 
#     def operateOnLine(self, line):
#         self.extractStatistic(line)
# 
#     def addData(self, datakey, data):
#         logger.debug("Reader %s adds data" % (self.getName()))
#         self.testrun.addData(datakey, data)
# 
#     def turnIntoFloat(self, astring):
#         """
#         parses strings to floats, keeps track of trailing caracters signifying magnitudes
# 
#         Special attention is put to strings of the form, e.g., '900k' where
#         the tailing 'k'-character signifies multiplication by 1000.
#         """
# 
#         lastelem = astring[-1]
#         multiplier = StatisticReader.multipliers.get(lastelem, 1.0)
# 
#         return float(astring.rstrip('kMG')) * multiplier
# 
# Path: ipet/misc/misc.py
# FLOAT_INFINITY = 1e20
# FLOAT_LARGE = 1e15
# DEFAULT_MIN_GEOM_MEAN = 1.0
#     FLOAT_INFINITY = infinity
# def sortingKeyContext(context):
# def filenameGetContext(filename):
# def getWordAtIndex(line : str, index : int) -> str:
# def getNumberAtIndex(line : str, index : int) -> str:
# def getSoluFileProbName(probname):
# def floatPrint(number, digitsbef=16, digitsafter=9, dispchar='g'):
# def getTexName(name):
# def getCplexGap(value, referencevalue):
# def getGap(value : float, referencevalue : float, useCplexGap : bool=False) -> float:
# def listGetArithmeticMean(listofnumbers):
# def iqr(listofnumbers):
# def lQuart(listofnumbers):
# def uQuart(listofnumbers):
# def shmean(listofnumbers, shiftby=10.0):
# def gemean(listofnumbers, mingeommean=DEFAULT_MIN_GEOM_MEAN):
# def listGetGeomMean(listofnumbers, mingeommean=DEFAULT_MIN_GEOM_MEAN):
# def listGetShiftedGeometricMean(listofnumbers, shiftby=10.0):
# def getVariabilityScore(listofnumbers):
# def isInfinite(value : float) -> bool:
# def getInfinity() -> float:
# def setInfinity(infinity : float):
# def cutString(string, char='_', maxlength=-1):
# def listGetMinColWidth(listofitems):
# def strConcat(strings : list) -> str:
# def meanOrConcat(l : list):
# def saveAsXML(nodeobject, filename : str) -> None:
# def convertTimeStamp(timestamp : float) -> str:


from .StatisticReader import StatisticReader
from ipet.misc import misc
import re
"""
The MIT License (MIT)

Copyright (c) 2018 Zuse Institute Berlin, www.zib.de

Permissions are granted as stated in the license file you have obtained
with this software. If you find the library useful for your purpose,
please refer to README.md for how to cite IPET.

@author: Gregor Hendel
"""


# Path: ipet/parsing/StatisticReader.py
# class StatisticReader(IpetNode):
#     """
#     base class for all statistic readers - readers should always inherit from this base class for minimal implementation
#     effort
# 
#     readers only need to overwrite the methods extractStatistic() and perhaps execEndOfProb()
#     """
# 
#     name = 'NO_NAME_DEFINED_YET'
#     regular_exp = re.compile('')
#     datakey = 'NO KEY'
#     datatype = float
#     lineindex = -1
# 
#     context = Key.CONTEXT_LOGFILE
# 
#     sleepAfterReturn = True
#     sleep = False
# 
#     multipliers = dict(k=1000, M=1e6, G=1e9)
# 
#     # the reader might behave differently depending on the solver type, due to the different output
#     SOLVERTYPE_SCIP = "SCIP"
#     SOLVERTYPE_GUROBI = "GUROBI"
#     SOLVERTYPE_CPLEX = "CPLEX"
#     SOLVERTYPE_CBC = "CBC"
#     SOLVERTYPE_XPRESS = "XPRESS"
#     SOLVERTYPE_COUENNE = "Couenne"
#     solvertype = SOLVERTYPE_SCIP
# 
#     @staticmethod
#     def boolfunction(value):
#         """ parses string TRUE or FALSE and returns the boolean value of this expression """
#         return True if value == "TRUE" else False
# 
#     @staticmethod
#     def changeSolverType(newtype):
#         StatisticReader.solvertype = newtype
# 
#     def setTestRun(self, testrun):
#         self.testrun = testrun
# 
#     def supportsContext(self, context):
#         """
#         returns True if the reader supports a given context, otherwise False
#         """
#         if type(self.context) is int:
#             return self.context == context
#         else:
#             return context in self.context
# 
#     def getSplitLineWithRegexp(self, regular_exp, line, index=-1, startofline=False):
#         if startofline == True and not re.match(regular_exp, line):
#             return None
#         if startofline == False and not re.search(regular_exp, line):
#             return None
# 
#         if index == -1:
#             return line.split()
#         else:
#             return line.split()[index]
# 
#     def getName(self):
#         """
#         returns the name of the StatisticReader
#         """
#         return self.name
# 
#     def extractStatistic(self, line):
#         """
#         overwrite this method for own reader subclasses
#         """
#         try:
#             if self.regular_exp.search(line):
#                 data = None
#                 try:
#                     data = self.datatype(misc.getWordAtIndex(line, self.lineindex))
#                 except ValueError:
#                     data = None
#                 except IndexError:
#                     data = None
#                 except TypeError:
# #                  print self.name, " failed data conversion"
#                     raise TypeError("Type error during data conversion in line <%s>" % line)
#                 self.addData(self.datakey, data)
#         except AttributeError:
# #          print self.name, " has no such attribute"
#             pass
# 
#     def execEndOfProb(self):
#         """
#         overwrite this method to implement final behaviour at the end of each problem, such as setting flags
#         """
#         return None
# 
#     def operateOnLine(self, line):
#         self.extractStatistic(line)
# 
#     def addData(self, datakey, data):
#         logger.debug("Reader %s adds data" % (self.getName()))
#         self.testrun.addData(datakey, data)
# 
#     def turnIntoFloat(self, astring):
#         """
#         parses strings to floats, keeps track of trailing caracters signifying magnitudes
# 
#         Special attention is put to strings of the form, e.g., '900k' where
#         the tailing 'k'-character signifies multiplication by 1000.
#         """
# 
#         lastelem = astring[-1]
#         multiplier = StatisticReader.multipliers.get(lastelem, 1.0)
# 
#         return float(astring.rstrip('kMG')) * multiplier
# 
# Path: ipet/misc/misc.py
# FLOAT_INFINITY = 1e20
# FLOAT_LARGE = 1e15
# DEFAULT_MIN_GEOM_MEAN = 1.0
#     FLOAT_INFINITY = infinity
# def sortingKeyContext(context):
# def filenameGetContext(filename):
# def getWordAtIndex(line : str, index : int) -> str:
# def getNumberAtIndex(line : str, index : int) -> str:
# def getSoluFileProbName(probname):
# def floatPrint(number, digitsbef=16, digitsafter=9, dispchar='g'):
# def getTexName(name):
# def getCplexGap(value, referencevalue):
# def getGap(value : float, referencevalue : float, useCplexGap : bool=False) -> float:
# def listGetArithmeticMean(listofnumbers):
# def iqr(listofnumbers):
# def lQuart(listofnumbers):
# def uQuart(listofnumbers):
# def shmean(listofnumbers, shiftby=10.0):
# def gemean(listofnumbers, mingeommean=DEFAULT_MIN_GEOM_MEAN):
# def listGetGeomMean(listofnumbers, mingeommean=DEFAULT_MIN_GEOM_MEAN):
# def listGetShiftedGeometricMean(listofnumbers, shiftby=10.0):
# def getVariabilityScore(listofnumbers):
# def isInfinite(value : float) -> bool:
# def getInfinity() -> float:
# def setInfinity(infinity : float):
# def cutString(string, char='_', maxlength=-1):
# def listGetMinColWidth(listofitems):
# def strConcat(strings : list) -> str:
# def meanOrConcat(l : list):
# def saveAsXML(nodeobject, filename : str) -> None:
# def convertTimeStamp(timestamp : float) -> str:


# Path: ipet/parsing/StatisticReader_CustomHistoryReader.py
from .StatisticReader import StatisticReader
from ipet.misc import misc
import re

"""
The MIT License (MIT)

Copyright (c) 2018 Zuse Institute Berlin, www.zib.de

Permissions are granted as stated in the license file you have obtained
with this software. If you find the library useful for your purpose,
please refer to README.md for how to cite IPET.

@author: Gregor Hendel
"""


class CustomHistoryReader(StatisticReader):