import collections
import math

from PyGenTools import makeGen
from PyArrTools import insort

def coordRotatedCCW(coord):
  return (-coord[1],coord[0])

def coordRotatedCW(coord):
  return (coord[1],-coord[0])

def coordSum(coords):
  result = (0,0)
  for coord in coords:
    result = (result[0] + coord[0], result[1] + coord[1])
  return result

def scaledCoord(coord,scalar):
  return (coord[0]*scalar,coord[1]*scalar)

def directionIndexToVector(index):
  return [(0,1),(1,0),(0,-1),(-1,0)][index]

def coordsAreNeighbors(coord0,coord1):
  assert len(coord0) == len(coord1)
  return all((abs(coord0[i]-coord1[i]) <= 1) for i in range(len(coord0)))

def distance(coord0,coord1):
  assert len(coord0) == len(coord1)
  return float(sum((coord0[i]-coord1[i])**2 for i in range(len(coord0))))**0.5

def magnitude(coord0):
  return float(sum(coord0Element**2 for coord0Element in coord0))**0.5

def sign(x):
  return int(math.copysign(1,x))

def signs(coord):
  return tuple([sign(value) for value in coord])

def modularMinimumDistance(value0,value1,modulus):
  distances = [item for item in [value0 - value1, value1 - value0, value0 + modulus - value1, value1 + modulus - value0] if item >= 0]
  return min(distances)

def spiralRingSideLength(ringIndex,includedCorners):
  assert includedCorners in [0,1,2]
  assert ringIndex > 0
  #if ringIndex == 0:
  #  result = spiralRingSideLength(ringIndex+1,includedCorners) - 4
  #  print("SpiralMath.spiralRingSideLength: returning {} instead of an error.".format(result))
  #  return result
  #  return Undefined("spiralRingSideLength is undefined for ringIndex=0")
  return ((2*ringIndex)-1)+includedCorners

def spiralRingLength(ringIndex):
  assert ringIndex >= 0
  if ringIndex == 0:
    return 1
  return 4 * spiralRingSideLength(ringIndex,1)

def spiralRingArea(ringIndex):
  if ringIndex == 0:
    return 1
  if ringIndex == 1:
    return 9
  return spiralRingSideLength(ringIndex,2)**2

def spiralRingInnerArea(ringIndex):
  #return sum(spiralRingLength(i) for i in range(ringIndex))
  if ringIndex == 0:
    return 0
  return spiralRingArea(ringIndex-1)

def spiralRingSideStartCoords(ringIndex):
  assert ringIndex > 0
  if ringIndex == 1:
    return [(0,1),(1,0),(0,-1),(-1,0)]
  return [(0-(ringIndex-1),ringIndex),(ringIndex,ringIndex-1),(ringIndex-1,-ringIndex),(-ringIndex,0-(ringIndex-1))]

def spiralRingSideMatchableCoords(ringIndex):
  assert ringIndex > 0
  if ringIndex == 1:
    return [(None,1),(1,None),(None,-1),(-1,None)]
  return [(None,ringIndex),(ringIndex,None),(None,-ringIndex),(-ringIndex,None)]

def spiralCoordEncode(coord, **customizationKwargs):
  basicCoord = decustomizedSpiralCoord(coord, **customizationKwargs)
  result = basicSpiralCoordEncode(basicCoord)
  return result

def spiralCoordDecode(t, **customizationKwargs):
  basicResult = basicSpiralCoordDecode(t)
  result = customizedSpiralCoord(basicResult, **customizationKwargs)
  return result

def decustomizedSpiralCoord(coord, home=None, rot=None, spin=None):
  assert len(coord) == 2 and len(home) == 2
  assert spin in [1,-1] #1 is CW, -1 is CCW.
  result = coordSum([coord,scaledCoord(home,-1)])
  for i in range(rot%4): #0 1 2 3 -> first step is N E S W
    result = coordRotatedCCW(result)
  result = (result[0]*spin, result[1])
  return result

def customizedSpiralCoord(coord, home=None, rot=None, spin=None):
  assert len(coord) == 2 and len(home) == 2
  assert spin in [1,-1] #1 is CW, -1 is CCW.
  result = (coord[0]*spin, coord[1])
  for i in range(rot%4): #0 1 2 3 -> first step is N E S W
    result = coordRotatedCW(result)
  result = coordSum([result, home])
  return result

def basicSpiralCoordDecode(t):
  assert t >= 0
  if t == 0: #because spiralRingSideLength can't handle ring index 0.
    return (0,0)

  ringIndex, tInRing = findSubdivisionAndInnerLocation(0, t, subdivisionSizeFun=spiralRingLength)

  sideLen = spiralRingSideLength(ringIndex, 1)
  sideInRing, tInSide = findSubdivisionAndInnerLocation(0, tInRing, subdivisionSize=sideLen)

  sideDirection = directionIndexToVector((sideInRing+1)%4)
  sideStartCoord = spiralRingSideStartCoords(ringIndex)[sideInRing]
  result = coordSum([sideStartCoord,scaledCoord(sideDirection,tInSide)])
  return result

def basicSpiralCoordEncode(coord):
  ringIndex = max(abs(value) for value in coord)
  if ringIndex == 0:
    return 0
  if ringIndex == 1: #because the side index finding loop can't handle ring 1.
    return {(0,1):1,(1,1):2,(1,0):3,(1,-1):4,(0,-1):5,(-1,-1):6,(-1,0):7,(-1,1):8}[coord]
  ringSideStartCoords = spiralRingSideStartCoords(ringIndex)
  ringSideMatchableCoords = spiralRingSideMatchableCoords(ringIndex)
  sideInRing = None
  sideMatches = []
  for sideIndex,testCoord in enumerate(ringSideMatchableCoords):
    if (coord[0] == testCoord[0] or coord[1] == testCoord[1]):
      sideMatches.append(sideIndex)
  if len(sideMatches) == 1:
    sideInRing = sideMatches[0]
  else:
    assert len(sideMatches) == 2
    offset = modularMinimumDistance(sideMatches[0],sideMatches[1],4)
    assert offset == 1
    if sideMatches == [0,3]:
      sideInRing = 3
    else:
      assert sideMatches in [[0,1],[1,2],[2,3]]
      sideInRing = min(sideMatches)
  assert sideInRing != None
  sideStartCoord = ringSideStartCoords[sideInRing]
  tPassedRings = spiralRingInnerArea(ringIndex)
  tPassedSides = (sideInRing*spiralRingSideLength(ringIndex,1))
  tWithinSide = int(round(distance(coord,sideStartCoord)))
  #print("(ringIndex,sideInRing,tPassedRings,tPassedSides,tWithinSide)="+str((ringIndex,sideInRing,tPassedRings,tPassedSides,tWithinSide))+".")
  t = tPassedRings + tPassedSides + tWithinSide
  return t

def findSubdivisionAndInnerLocation(startingSubdivisionIndex, absoluteLocation, subdivisionSize=None, subdivisionSizeFun=None): #this can be modified to work in higher dimensions.
  assert not (subdivisionSize == None and subdivisionSizeFun == None)
  if subdivisionSizeFun == None:
    subdivisionSizeFun = (lambda ignore: subdivisionSize)

  currentSubdivisionIndex = startingSubdivisionIndex
  relativeLocation = absoluteLocation
  while True:
    currentSubdivisionSize = subdivisionSizeFun(currentSubdivisionIndex)
    if currentSubdivisionSize > relativeLocation:
      break
    relativeLocation -= currentSubdivisionSize
    currentSubdivisionIndex += 1
  return currentSubdivisionIndex, relativeLocation

def genSpiralCoords(*args, **customizationKwargs):
  for basicCoord in genBasicSpiralCoords(*args):
    yield customizedSpiralCoord(basicCoord, **customizationKwargs)

def genBasicSpiralCoords(*args):
  #4 to 8 times faster for large spirals.
  startT = 0
  endTExclusive = None
  direction = 1

  if len(args) == 1:
    endTExclusive = args[0]
    assert endTExclusive >= -1
  if len(args) >= 2:
    startT, endTExclusive = args[0], args[1]
    assert startT >= 0
    assert endTExclusive >= -1 #do stricter checks later.
  if len(args) >= 3:
    direction = args[2]
    assert direction in [1, -1]
  if len(args) > 3:
    raise ValueError("wrong number of arguments.")

  if endTExclusive != None:
    endT = endTExclusive - direction
    assert endT >= 0
  else:
    endT = None

  startRingIndex, startTInStartRing = findSubdivisionAndInnerLocation(0, startT, subdivisionSizeFun=spiralRingLength)
  if startRingIndex > 0:
    startSideLen = spiralRingSideLength(startRingIndex, 1)
    startSideInStartRing, startTInStartSide = findSubdivisionAndInnerLocation(0, startTInStartRing, subdivisionSize=startSideLen)

  if endT == None:
    endRingIndex, endTInEndRing = None, None
    endSideInEndRing, endTInEndSide = None, None
  else:
    endRingIndex, endTInEndRing = findSubdivisionAndInnerLocation(0, endT, subdivisionSizeFun=spiralRingLength)
    if endRingIndex > 0:
      endSideLen = spiralRingSideLength(endRingIndex, 1)
      endSideInEndRing, endTInEndSide = findSubdivisionAndInnerLocation(0, endTInEndRing, subdivisionSize=endSideLen)

  ringIndex = startRingIndex

  if ringIndex == endRingIndex:
    for outputItem in genBasicSpiralRingCoords(ringIndex,startTInStartRing,endTInEndRing,direction):
      yield outputItem
    return
  else:
    for outputItem in genBasicSpiralRingCoords(ringIndex,startTInStartRing,None,direction):
      yield outputItem
    ringIndex += direction

  while ringIndex != endRingIndex: #iterate ringIndex
    #print("ringIndex",ringIndex)
    if ringIndex == 0:
      yield (0,0)
      assert direction < 0
    for outputItem in genBasicSpiralRingCoords(ringIndex,None,None,direction):
      yield outputItem
    ringIndex += direction

  assert ringIndex == endRingIndex
  if ringIndex == 0:
    yield (0,0)
    return

  for outputItem in genBasicSpiralRingCoords(ringIndex,None,endTInEndRing,direction):
    yield outputItem
  return

def genBasicSpiralRingCoords(ringIndex,startTInRing,endTInRing,direction):
  #print("genBasicSpiralRingCoords: ringIndex={}, startTInRing={}, endTInRing={}, direction={}.".format(ringIndex,startTInRing,endTInRing,direction))
  if ringIndex == 0:
    if startTInRing in [0,None] and endTInRing in [0,None]:
      yield (0,0)
      return
    else:
      raise ValueError("the conditions to work with ringIndex=0 are not met. startTInRing and endTInRing each must be either 0 or None.")
  sideLen = spiralRingSideLength(ringIndex, 1)

  if startTInRing != None:
    startSideInRing, startTInStartSide = findSubdivisionAndInnerLocation(0, startTInRing, subdivisionSize=sideLen)
    sideInRingRangeStart = startSideInRing
  else:
    startSideInRing, startTInStartSide = (None, None)
    sideInRingRangeStart = 0 if direction > 0 else 3

  if endTInRing != None:
    endSideInRing, endTInEndSide = findSubdivisionAndInnerLocation(0, endTInRing, subdivisionSize=sideLen)
    sideInRingSeqEnd = endSideInRing
  else:
    endSideInRing, endTInEndSide = (None,None)
    sideInRingSeqEnd = 3 if direction > 0 else 0

  sideInRingSeq = range(sideInRingRangeStart, sideInRingSeqEnd + sign(direction), direction)

  basicTInSideRangeStart = 0 if direction > 0 else sideLen-1
  basicTInSideRangeEnd = sideLen if direction > 0 else -1

  #print("genBasicSpiralRingCoords: (startSideInRing,startTInStartSide,sideInRingRangeStart)="+str((startSideInRing, startTInStartSide, sideInRingRangeStart)))
  #print("genBasicSpiralRingCoords: (endSideInRing,endTInEndSide,sideInRingSeqEnd)="+str((endSideInRing, endTInEndSide, sideInRingSeqEnd)))
  #print("genBasicSpiralRingCoords: (basicTInSideRangeStart,basicTInSideRangeEnd)="+str((basicTInSideRangeStart, basicTInSideRangeEnd)))

  #print("genBasicSpiralRingCoords: sideInRingSeq={}".format(sideInRingSeq)) #THIS LINE NOT PYTHON3 COMPATIBLE.

  for sideInRing in sideInRingSeq: #iterate sideInRing
    tInSideSeq = range(startTInStartSide if sideInRing==startSideInRing else basicTInSideRangeStart, endTInEndSide+direction if sideInRing==endSideInRing else basicTInSideRangeEnd, direction)
    sideDirection = directionIndexToVector((sideInRing+1)%4)
    sideStartCoord = spiralRingSideStartCoords(ringIndex)[sideInRing]
    #print("genBasicSpiralRingCoords: sideInRing={}, tInSideSeq={}.".format(sideInRing,tInSideSeq))
    for tInSide in tInSideSeq:
      result = coordSum([sideStartCoord,scaledCoord(sideDirection,tInSide)])
      #print("genBasicSpiralRingCoords: sideInRing={}, tInSide={}, yielding {}.".format(sideInRing,tInSide,result))
      yield result
  return

def genCircularSpiralCoords(**customizationKwargs):
  for basicCoord in genBasicCircularSpiralCoords():
    yield customizedSpiralCoord(basicCoord, **customizationKwargs)

def genBasicCircularSpiralCoords():
  return genDezigged(genBasicSpiralCoords(), keyFun=magnitude)

def genDezigged(inputSeq, forbidLocalMinimaDecrease=True, forbidLocalMaximaDecrease=True, keyFun=None):
  if keyFun == None:
    keyFun = (lambda x: x)
  inputGen = makeGen(inputSeq)

  rememberedLocalMinima = collections.deque()
  rememberedLocalMaxima = collections.deque()
  history = []
  currentTriplet = collections.deque()

  sortKeyFun = (lambda itemA: itemA[0])

  #getStatus = (lambda: "status:(history={}, rlmn={}, rlmx={}, triplet={}, canOutputNow()={})".format(history, rememberedLocalMinima, rememberedLocalMaxima, currentTriplet, canOutputNow()))

  if forbidLocalMinimaDecrease and forbidLocalMaximaDecrease:
    def localExtremaAllowOutputNow():
      testResult = sortKeyFun(rememberedLocalMinima[-1]) > sortKeyFun(rememberedLocalMaxima[0])
      #maybe they could be popped now?
      return testResult
  else:
    def localExtremaAllowOutputNow():
      return sortKeyFun(max(rememberedLocalMinima, key=sortKeyFun)) > sortKeyFun(min(rememberedLocalMaxima, key=sortKeyFun))

  def canOutputNow():
    if len(history) == 0:
      return False
    if len(rememberedLocalMinima) == 0 or len(rememberedLocalMaxima) == 0:
      return False
    return localExtremaAllowOutputNow()

  def detectLocalExtrema(suspendRules=False):
    assert len(currentTriplet) in [2,3]
    if sortKeyFun(min(currentTriplet ,key=sortKeyFun)) == sortKeyFun(currentTriplet[1]):
      if forbidLocalMinimaDecrease and not suspendRules:
        if len(rememberedLocalMinima) > 0:
          if not sortKeyFun(rememberedLocalMinima[-1]) <= sortKeyFun(currentTriplet[1]):
            raise ValueError("forbidLocalMinimaDecrease violated by inputSeq!")
      #print("SpiralMath.genDezigged.detectLocalExtrema: detected local minimum {}. before registering, {}.".format(currentTriplet[1], getStatus()))
      rememberedLocalMinima.append(currentTriplet[1])
      #print("SpiralMath.genDezigged.detectLocalExtrema: detected local minimum {}. after registering, {}.\n".format(currentTriplet[1], getStatus()))
    if sortKeyFun(max(currentTriplet, key=sortKeyFun)) == sortKeyFun(currentTriplet[1]):
      if forbidLocalMaximaDecrease and not suspendRules:
        if len(rememberedLocalMaxima) > 0:
          if not sortKeyFun(rememberedLocalMaxima[-1]) <= sortKeyFun(currentTriplet[1]):
            raise ValueError("forbidLocalMaximaDecrease violated by inputSeq!")
      #print("SpiralMath.genDezigged.detectLocalExtrema: detected local maximum {}. before registering, {}.".format(currentTriplet[1], getStatus()))
      rememberedLocalMaxima.append(currentTriplet[1])
      #print("SpiralMath.genDezigged.detectLocalExtrema: detected local maximum {}. after registering, {}.\n".format(currentTriplet[1], getStatus()))

  currentTripletFilledBefore = False
  inputItemsExhausted = False

  while True:
    assert len(currentTriplet) <= 3
    if len(currentTriplet) == 3:
      currentTripletFilledBefore = True

    if canOutputNow():
      #print("SpiralMath.genDezigged: normal out: {}, yielding {}.\n".format(getStatus(), history[0][1]))
      yield history[0][1]
      if forbidLocalMinimaDecrease:
        if history[0] == rememberedLocalMinima[0]:
          rememberedLocalMinima.popleft()
      else:
        raise NotImplementedError("There is currently no way to remove items from rememberedLocalMaxima when they are not sorted. Try forbidding decreases in them.")
      if forbidLocalMaximaDecrease:
        if history[0] == rememberedLocalMaxima[0]:
          rememberedLocalMaxima.popleft()
      else:
        raise NotImplementedError("There is currently no way to remove items from rememberedLocalMaxima when they are not sorted. Try forbidding decreases in them.")
      del history[0] #@ slow!
      continue

    try:
      nextValue = next(inputGen)
      nextKey = keyFun(nextValue)
      nextItem = (nextKey, nextValue)
      #print("SpiralMath.genDezigged: notice: {}, ingesting {}.".format(getStatus(), nextItem))
      assert len(currentTriplet) <= 3
      currentTriplet.append(nextItem)
      insort(history, nextItem, stable=True, keyFun=sortKeyFun)
      #print("SpiralMath.genDezigged: notice: {}, ingested {}.\n".format(getStatus(), nextItem))

    except StopIteration:
      inputItemsExhausted = True

    if currentTripletFilledBefore:
      currentTriplet.popleft() #to make up for not doing it earlier in the try block above.
      assert len(currentTriplet) <= 3

      if len(currentTriplet) == 3:
        detectLocalExtrema()
        continue
      elif len(currentTriplet) == 2:
        assert inputItemsExhausted, "if not, then why is currentTriplet less than full?"
        detectLocalExtrema(suspendRules=True)
        continue
      elif len(currentTriplet) == 1:
        pass #allow endgame.
      elif len(currentTriplet) == 0:
        raise ValueError()
      else:
        assert False
    else:
      continue #don't reach the endgame before the right time.

    assert len(currentTriplet) == 1
    assert inputItemsExhausted

    for endgameItem in sorted(history):

      #print("SpiralMath.genDezigged: endgame out: {}, yielding {}.\n".format(getStatus(), history[0][1]))
      yield endgameItem[1]
    return

  assert False, "unreachable statement."

for rotationDirection in [-1,1]:
  for startDirection in [0,1,2,3]:
    for startPosition in [(0,0),(20,100)]:
      assert [spiralCoordEncode(spiralCoordDecode(i,home=startPosition,rot=startDirection,spin=rotationDirection),home=startPosition,rot=startDirection,spin=rotationDirection) for i in range(50)] == [i for i in range(50)]

assert [basicSpiralCoordDecode(t) for t in range(16)] == [(0, 0), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1), (-1, 2), (0, 2), (1, 2), (2, 2), (2, 1), (2, 0), (2, -1)]


"""
A class that contains a Hebrew passage, consisting of paragraphs
as marked by a petach (פ) or samech (ס) in the Masoretic Text. If
a book like Psalms, which lacks paragaph markers, is encountered,
the passages are split at the chapter level.
"""
class Passage:

    def __init__(self, id):
        self.id = id
        self.verses = [] # a list of verse node ints.
        self.words = [] # a list of word node ints.
        self.start_word = 0
        self.end_word = 0
        self.start_verse = 0
        self.end_verse = 0
        self.word_count = 0
        self.weight0 = 0
        self.weight1 = 0
        self.weight2a = 0 # all words denom
        self.weight2b = 0 # unique words
        self.weight3a = 0 # all word denom
        self.weight3b = 0
        self.weight3c = 0 #3a with morph
        self.verb_types_present = set()
        self.verb_stems_present = set()
        self.word_ranks_data = {}
        self.start_ref = ''
        self.end_ref = ''

    paragraph_markers = {'פ': 'open', 'ס': 'closed'}

    # Returns a list of all words present in the passage.
    def get_all_words(self):
        words = []
        for verse in self.verses:
            for word in L.i(verse, otype='word'):
                words.append(word)
        return words

    # Returns a list of all words present in a specified verse in the passage.
    def get_vs_words(self, verse):
        verse_words = [w for w in L.i(verse, otype='word')]
        return verse_words

    # Returns a String of all the text in the passage.
    def get_text(self):
        return T.text(self.verses, fmt='text-orig-full')

    """
    get_vs_weights() returns a dictionary mapping each verse node in
    the passage to a weight. It takes rank_scale as input, an instance
    of Classify(args).rank_scale() (see notes in Classify for instantiaion).
    """
    def get_vs_weights(self, rank_scale):
        # A dictionary mapping verse nodes to weights.
        verse_weights = {}
        # Iterate over verses in the passage.
        for verse in self.verses:
            verse_weight = 0
            words = self.get_vs_words(verse)
            # Add the scaled word weights to the verse's total weight.
            for word in words:
                if F.voc_lex_utf8.v(word) not in Classify().stop_words:
                    for rank in rank_scale.keys():
                        lex_freq = F.freq_lex.v(word)
                        _range = rank_scale[rank]['range']
                        if lex_freq >= _range[0] and lex_freq < _range[1]:
                            verse_weight += rank_scale[rank]['weight']
            # Add the verse's weight to the dictionary at this verse's key.
            verse_weight /= len(words)
            verse_weights[verse] = round(verse_weight, 4)

        return verse_weights

    # Simply add the freq_lex of each word to weight.
    def get_passage_weight0(self):
        total_weight = 0
        # Iterate over words in the passage.
        for word in self.words:
            if F.voc_lex_utf8.v(word) not in Classify().stop_words:
                # Subtract 10000 to penalize rare words.
                total_weight += 10000 - F.freq_lex.v(word)
        total_weight /= len(self.words)

        return round(total_weight, 4)

    def get_passage_weight1(self, rank_scale):
        total_weight = 0
        # Iterate over words in the passage.
        for word in self.words:
            if F.voc_lex_utf8.v(word) not in Classify().stop_words:
                # Iterate over the ranks present in the rank scale.
                for rank in rank_scale.keys():
                    lex_freq = F.freq_lex.v(word)
                    _range = rank_scale[rank]['range']
                    if lex_freq >= _range[0] and lex_freq < _range[1]:
                        # Give a half penalty for proper nouns.
                        if F.sp.v(word) == 'nmpr': # proper noun
                            total_weight += (rank_scale[rank]['weight']) / 2
                        # Give a full penalty for other word types.
                        else:
                            total_weight += rank_scale[rank]['weight']
        total_weight /= len(self.words)

        return round(total_weight, 4)

    # Only penalize once per lexical value.
    def get_passage_weight2(self, rank_scale, div_all=True):
        total_weight = 0
        unique_words = set()
        # Iterate over words in the passage.
        for word in self.words:
            lex = F.voc_lex_utf8.v(word)
            if lex not in Classify().stop_words and lex not in unique_words:
                # Iterate over the ranks present in the rank scale.
                for rank in rank_scale.keys():
                    lex_freq = F.freq_lex.v(word)
                    _range = rank_scale[rank]['range']
                    if lex_freq >= _range[0] and lex_freq < _range[1]:
                        # Give a half penalty for proper nouns.
                        if F.sp.v(word) == 'nmpr': # proper noun
                            total_weight += (rank_scale[rank]['weight']) / 2
                        # Give a full penalty for other word types.
                        else:
                            total_weight += rank_scale[rank]['weight']
                unique_words.add(lex)
        # Compare using all words as denominator vs. unique words.
        if div_all:
            total_weight /= len(self.words)
        else:
            total_weight /= len(unique_words)

        return round(total_weight, 4)

    # Decrease penalty for each occurance.
    def get_passage_weight3(self, rank_scale, div_all=True, morph=False):
        word_weights = {}
        verb_count = 0
        verb_weight = 0
        min_penalty = 1.7 # min penalty for rare words and proper nouns.
        # Iterate over words in the passage.
        for word in self.words:
            lex = F.voc_lex_utf8.v(word)
            if lex not in Classify().stop_words:
                # Add partial penalty for reocurring words.
                if lex in word_weights.keys():
                    # Only gradually decrease penalty for rarer words.
                    # Decreases by 1 point per occurance.
                    word_weights[lex]['count'] += 1
                    if F.freq_lex.v(word) < 100:
                        count = word_weights[lex]['count']
                        penalty = word_weights[lex]['penalty']
                        new_weight = penalty - count
                        added_weight = new_weight if new_weight >= min_penalty else min_penalty
                        word_weights[lex]['weight'] += added_weight
                    else:
                        word_weights[lex]['weight'] += word_weights[lex]['penalty']
                # Add full penalty for the first occurance.
                else:
                    # Add word to hash table
                    word_weights[lex] = {'count':0, 'weight':0, 'penalty':0}
                    # Iterate over the ranks present in the rank scale.
                    for rank in rank_scale.keys():
                        lex_freq = F.freq_lex.v(word)
                        _range = rank_scale[rank]['range']
                        if lex_freq >= _range[0] and lex_freq < _range[1]:
                            # Give a half penalty for proper nouns.
                            _penalty = rank_scale[rank]['weight']
                            if F.sp.v(word) == 'nmpr' and _penalty > min_penalty: # proper noun
                                word_weights[lex]['penalty'] = int(math.ceil(_penalty / 2))
                            # Give a full penalty for other word types.
                            else:
                                word_weights[lex]['penalty'] = _penalty
                    word_weights[lex]['weight'] += word_weights[lex]['penalty']
                    word_weights[lex]['count'] += 1
                # If we're penalizing for morphology
                if morph:
                    if F.sp.v(word) == 'verb':
                        verb_count += 1
                        verb_weight += MorphRank.stem_map.get(F.vs.v(word),0) + MorphRank.tense_map[F.vt.v(word)]

        # Get the sum of all word weights.
        total_weight = sum([w for w in [word_weights[k]['weight'] for k in word_weights.keys()]])
        # Compare using all words as denominator vs. unique words.
        if div_all:
            total_weight = total_weight / len(self.words) + (verb_weight / len(self.words))
        else:
            total_weight /= len(word_weights)

        return round(total_weight, 4)

"""
A class to store passages. It includes methods to sort the passages
by attributes such as word count, weight, and canonical order. It
also stores the rank scale used to create the passage list. The passages
will be stored in order_sorted by default.
"""
class Passages:

    def __init__(self, passages, rank_scale={}):
        self.rank_scale = rank_scale
        self.order_sorted = passages
        self.word_count_sorted = self.word_count_sort()
        self.weight_sorted0 = self.weight_sort0()
        self.weight_sorted1 = self.weight_sort1()
        self.weight_sorted2a = self.weight_sort2a()
        self.weight_sorted2b = self.weight_sort2b()
        self.weight_sorted3a = self.weight_sort3a()
        self.weight_sorted3b = self.weight_sort3b()
        self.weight_sorted3c = self.weight_sort3c()

    def word_count_sort(self):
        return sorted(self.order_sorted, key=lambda p: p.word_count)

    """ For weight sorts I use a dict mapping Passage objects to their rank
    number so that I can then compare all the weight sorts in a dataframe. """
    def weight_sort0(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight0)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    def weight_sort1(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight1)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    def weight_sort2a(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight2a)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    def weight_sort2b(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight2b)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    def weight_sort3a(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight3a)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    def weight_sort3b(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight3b)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    # Morph
    def weight_sort3c(self):
        sorted_list = sorted(self.order_sorted, key=lambda p: p.weight3c)
        return {sorted_list[i]:i for i in range(len(sorted_list))}

    # A function to display the rank scale as a multi-line string.
    def print_scale(self):
        scale = self.rank_scale
        output_text = ""
        for i, rank in enumerate(scale.ranks):
            _range = scale.ranges[i]
            weight = scale.weights[i]
            output = f"{weight}\t{_range[0]}-{_range[1]} occ"
            output_text += f"{rank}:   \t{output}\n"
        return output_text


#!/usr/bin/env python
# coding: utf-8
from collections import defaultdict
# In[14]:

## HAY ERROR EN EL CALENDARIO, EL ALGORITMO ESTA BN PERO EL CALENDARIO NO RECONOCE LA OCUPACIO DE PACIENTES EN LOS OTROS DIAS.
asient = 5 ## cambiar a 14
semanas_de_simulacion = 41

dias = ["lunes", "martes", "miercoles", "jueves","viernes", "sabado"]
calendario = defaultdict(defaultdict)

class Modulo:
    def __init__(self, identificador):
        self.paciente = None
        self.ocupado = False
        self.necesita_enfermera = False
        self.identificador = None

cuenta = 0
for i in range(semanas_de_simulacion):
    semana = defaultdict(defaultdict)
    for j in dias:
        asiento = defaultdict(defaultdict)
        for k in range(1, asient + 1): ### numero asientos
            modulo = defaultdict(classmethod)
            for u in range(1, 41):  # numero modulos
                cuenta += 1
                modulo[u] = Modulo(cuenta)
            asiento[k] = modulo
        semana[j] = asiento
    calendario[i] = semana


path = "C:/Users/Brendan van Walstijn/Documents/Power Monitoring/SavedData.txt"

def filter_content(content):
    sentence = str(content)

    # split at backslash
    sentence_list = sentence.split('\\')
    for word in sentence_list:
        if 'nVoltage' in word:
            voltage_final_sentence = word.split(' ')
            # string_to_append.append('c ' + voltage_final_sentence[1] + ' ' + identifier + ' ')

            f = open(path, 'a')
            f.write('c ' + voltage_final_sentence[1] +'\n')
            f.close()

        if 'nPower_usage' in word:
            power_final_sentence = word.split(' ')
            # string_to_append.append('p ' + power_final_sentence[1] + ' ' + identifier + '\n')

            f = open(path,'a')
            f.write('p ' + power_final_sentence[1] + '\n')
            f.write('\n')
            f.close()


class IPv4Trie:
    def __init__(self):
        self.head = IPv4Node()

    def insert(self, cidr, obj):
        bit_array = IPv4Util.get_bit_array_from_ipv4_cidr(cidr)

        node = self.head
        for bit in bit_array:
            if bit not in node.children:
                node.children[bit] = IPv4Node(bit)
            node = node.children[bit]
        node.is_end = True
        node.cidr = IPv4Util.get_standard_cidr(cidr)
        node.obj = obj

    def find_all(self, cidr):
        result = []
        bit_array = IPv4Util.get_bit_array_from_ipv4_cidr(cidr)

        node = self.head
        if node.is_end:
            result.append((node.cidr, node.obj))
        for bit in bit_array:
            if bit not in node.children:
                return result
            node = node.children[bit]
            if node.is_end:
                result.append((node.cidr, node.obj))
        return result

class IPv4Node:
    def __init__(self, value = False):
        self.children = {}
        self.is_end = False
        self.value = value
        self.cidr = ""
        self.obj = None

class IPv4Util:
    @staticmethod
    def get_bit_array_from_ipv4_cidr(cidr):
        splitted = cidr.split("/")
        if len(splitted) == 0 or len(splitted) > 2:
            raise ValueError("{} is not a valid IPv4 or CIDR.".format(cidr))
        ip = splitted[0]
        length_str = "32" if len(splitted) == 1 else splitted[1]
        if not length_str.isdigit():
            raise ValueError("{} is not a valid IPv4 or CIDR.".format(cidr))
        length = int(length_str)

        splitted = ip.split(".")
        if len(splitted) != 4:
            raise ValueError("{} is not a valid IPv4 or CIDR.".format(cidr))

        for segment in splitted:
            if not segment.isdigit():
                raise ValueError("{} is not a valid IPv4 or CIDR.".format(cidr))
            value = int(segment)
            if value < 0 or value > 255:
                raise ValueError("{} is not a valid IPv4 or CIDR.".format(cidr))

        result = []
        if length == 0:
            return result
        index = 0
        for segment in splitted:
            bits = IPv4Util.get_8_bit_list(cidr, segment)
            for i in range(8):
                result.append(bits[i])
                index += 1
                if index == length:
                    return result
        return result

    @staticmethod
    def get_8_bit_list(cidr, segment):
        binary = "{0:b}".format(int(segment))

        result = []
        for _ in range(8 - len(binary)):
            result.append(False)
        for i in range(len(binary)):
            result.append(bool(int(binary[i])))

        return result

    # Standarlize cidr. For example, 0.1.2.3/0 => 0.0.0.0/0
    @staticmethod
    def get_standard_cidr(cidr):
        bit_array = IPv4Util.get_bit_array_from_ipv4_cidr(cidr)
        length = len(bit_array)
        for _ in range(32 - length):
            bit_array.append(False)

        str_list = []
        for i in range(4):
            segment_chars = []
            for j in range(8):
                segment_chars.append(str(int(bit_array[i * 8 + j])))
            str_list.append(str(int("".join(segment_chars), 2)))
            if i < 3:
                str_list.append(".")

        str_list.append("/")
        str_list.append(str(length))
        return "".join(str_list)


# -*- encoding: utf-8 -*-

'''
把当前目录下的图片文件按拍摄日期进行重命名
如果没有拍摄日期，按修改日期重命名

如果遇到同一时刻的两张图，不覆盖，给同时刻的后面的图片的名字里加上时间戳，
然后人工处理。
'''

import os
import datetime
import shutil
import exifread
import time

def get_file_modification_date(file_name):
    '''
    获得文件修改时间
    '''
    # 获得文件创建时间戳
    file_modification_timestamp = os.path.getmtime(file_name)
    # 转换为创建时间
    file_modification_time = datetime.datetime.fromtimestamp(file_modification_timestamp)
    # 转换为创建日期
    file_modification_date = file_modification_time.strftime('%Y-%m-%d %H.%M.%S')
    return file_modification_date

def get_file_date(file_name):
    '''
    获得文件拍摄时间，如果没有拍摄时间，用修改时间代替
    '''
    try:
        with open(file_name, 'rb') as file:
            original_data = exifread.process_file(file)
    except:
        return "000"

    try:
        file_origin_date = original_data['EXIF DateTimeOriginal']
        file_date = str(file_origin_date)[:10].replace(':', '-') # 文件日期
        file_time = str(file_origin_date)[11:19].replace(':', '.') # 文件时间
        final_file_datetime = file_date + " " + file_time # 文件日期+时间

        return str(final_file_datetime)
    except:
        return get_file_modification_date(file_name)

def get_current_dir_files():
    '''
    获得当前目录的所有文件，排除.py文件
    '''
    # 获得当前目录的所有文件和文件夹
    files_and_dirs = os.listdir()
    # 过滤文件夹
    files = [file for file in files_and_dirs if (os.path.isfile(file) and file[-3:] != '.py')]
    return files

def create_dir(dir_name):
    # 文件夹不存在是创建文件夹
    if not os.path.isdir(dir_name):
        os.mkdir(dir_name)

if __name__ == '__main__':
    files = get_current_dir_files()
    print('共%d个文件' % len(files))

    for index, file in enumerate(files):
        file_date = get_file_date(file)

        # 跳过异常文件
        if file_date == "000":
            continue

        # 源文件名和目标文件名
        source_file_name = file
        file_type = os.path.splitext(file)[-1]
        target_file_name = file_date + file_type

        # 跳过命名正确的文件
        if source_file_name == target_file_name:
            continue

        try:
            os.rename(source_file_name, target_file_name)
        except:
            # 遇到同时刻的文件，名字里加上现在的时间戳
            target_file_name = file_date + "(" + str(time.time()) + ")" + file_type
            os.rename(source_file_name, target_file_name)

        print('第%d个' % (index + 1))
    print('完成!!!')


"""Unit tests for netbox-netisp ."""

from django.test import TestCase
from netbox_netisp.models import Customer, Address, Account
from datetime import datetime

class CustomerTestCase(TestCase):
    """Test the Customer"""

    def setUp(self):
        """Create a customer object with sample data"""
        Customer.objects.create(
            first_name="Schylar",
            middle_name="S",
            last_name="Utley",
            birthdate=datetime(1997, 2, 10, 16, 13, 49, 71549),
        )

    def test_customer_name(self):
        """Verify that the name is being joined correctly"""
        sutley = Customer.objects.get(first_name="Schylar")
        self.assertEqual(sutley.name(), "Schylar S Utley")

    def test_customer_age(self):
        """Verify that the customer has a valid age"""
        sutley = Customer.objects.get(first_name="Schylar")
        self.assertGreaterEqual(sutley.age(), 1)

class AddressTestCase(TestCase):
    def setUp(self):
        addr1 = Address.objects.create(
            street_number=1502,
            street_name="Main",
            street_suffix="Ave",
            city="Webb City",
            state_code="MO",
            zip="64870-1234",
            slug="f",
        )

    def test_address_name_without_ord(self):
        address = Address.objects.get(slug="f")
        self.assertEqual("1502 Main Ave, Webb City MO, 64870-1234", str(address))

    def test_address_name_with_ord(self):
        address = Address.objects.get(slug="f")
        address.street_ordinance = "S"
        self.assertEqual("1502 S. Main Ave, Webb City MO, 64870-1234", str(address))

class AccountTestCase(TestCase):
    """Test the Account"""

    def setUp(self):
        """Create an account object with sample data"""
        customer = Customer.objects.create(
            first_name="Tom",
            middle_name="S",
            last_name="Riddle",
            birthdate=datetime(1997, 2, 10, 16, 13, 49, 71549),
        )

        Account.objects.create(primary_applicant=customer)

    def test_applicant_name(self):
        account = Account.objects.get(pk=1)
        self.assertEqual("Tom S Riddle", account.primary_applicant.name())


import re

def parse(pp_command: str) -> tuple[set, dict, str, set, dict, list]:
    '''
    Parse command string and return command information
    Returns:
        (general_flags: set, general_options: dict, command: str, command_flags: set, command_options: dict, others: list)
    '''
    args = pp_command.split()

    command = ""
    general_flags = set()
    general_options = {}

    command_flags = set()
    command_options = {}
    others = []

    index = 0
    flags = general_flags
    options = general_options
    while index < len(args):
        arg = args[index]

        if arg == '/pp':
            index += 1
            continue

        if arg.startswith('--'):
            flags.add(arg)
            index += 1

        elif arg[0] == '-':
            if index + 1 >= len(args):
                return f"please provide input value for '{arg}'"

            value = args[index + 1]

            if value[0] == '-':
                return f"please provide input value for '{arg}'"

            options[arg] = value
            index += 2

        elif command == '':
            command = arg
            options = command_options
            index += 1

        else:
            others.append(arg)
            index += 1

    return (general_flags, general_options, command, command_flags, command_options, others)


import random
counter = 0
index_select = 0
for x in range(20):
    tournament = "Champions League", "EPL", "La Liga", "Seria A", "Bundesliga A", "Carabao Cup", "Europa League", "Club World cup"
    organisation = "UEFA", "The Premier League", "Spanish FA", "Italian FA", "German FA", "English FA", "UEFA", "FIFA"
    per_tournament = tournament[random.randint(0, len(tournament) - 1)]
    per_organisation = organisation[tournament.index(per_tournament)]
    counter +=1
    print("INSERT" + " INTO epl.Tournament VALUES(" + str(counter) + "," ,"'" + per_tournament+"'" + "," ,"'" +per_organisation+"'" +");")
    index_select +=1


import itertools
import os
import re
import xml.etree.ElementTree as ET

# pattern to filiter only amharic words
pattern  = re.compile(r'[ሀ-ፚ\s]+', re.DEBUG)
input_dir = "dataset/text/AA"
output_path = "dataset/amwiki.txt"
texts = []
for file in os.listdir(input_dir):
    with open(os.path.join(input_dir, file)) as f:
        it = itertools.chain('<root>', f, '</root>')
        root = ET.fromstringlist(it)
    for doc in root.findall("doc"):
        doc_txt = ""
        for match in pattern.findall(doc.text.strip()):
            doc_txt+= match.strip().replace("\n"," ")
        texts.append(doc_txt)

all_texts = "\n".join(texts)

with open (output_path,"w+") as f:
    f.write(all_texts + "\n")


#   1. R2를 음수가 아닌 0.5 이하로 줄이기
#   2. 데이터는 건들지 말것
#   3. 레이어는 인풋 아웃풋 포함 7개 이상
#   4. batch_size=1
#   5. 히든레이어의 노드는 각각 10개 이상 100개 이하
#   6. train 70%
#   7. epoch 100번 이상
#   8. loss지표는 mse 또는 mae
#   9. activation 사용 금지

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
import numpy as np
from sklearn.model_selection import train_test_split

#1. 데이터
x = np.array(range(1,21))
y = np.array(range(1,21))

x_train, x_test, y_train, y_test = train_test_split(x, y,
    train_size=0.7, shuffle=True, random_state=123
)

#2. 모델구성
model = Sequential()
model.add(Dense(10, input_dim = 1))
model.add(Dense(10))
model.add(Dense(10))
model.add(Dense(10))
model.add(Dense(10))
model.add(Dense(1))

#3. 컴파일, 훈련
model.compile(loss='mse', optimizer='adam',
              metrics=['mae'])                                  #   metrics는 훈련에 영향을 미치진 않지만 값은 나온다.
                                                                #   acc와 accuracy는 동일
                                                                #   error가 그 다음 가중치 갱신을 할때 영향을 미친다.(훈련에 영향을 미친다.)
model.fit(x_train, y_train, epochs=100, batch_size=1)           #   가중치 생성

#4. 평가, 예측
loss = model.evaluate(x_test, y_test)                           #   test 데이터로 평가
print('loss : ', loss)

y_predict = model.predict(x_test)                               #   최적의 가중치

print("=============")
print(y_test)
print(y_predict)
print("=============")

from sklearn.metrics import mean_squared_error, r2_score
def RMSE(y_test, y_predict):
    return np.sqrt(mean_squared_error(y_test, y_predict))
print("RMSE : ", RMSE(y_test, y_predict))

r2 = r2_score(y_test, y_predict)
print("R2 : ", r2)


import pyodbc as po
import pandas as pd
#import sqlite3
#import mysql.connector
#import mysql.connector
#from mysql.connector import Error
#from mysql.connector import Error
#import re, nltk
import pyodbc as po
import pandas as pd
from datetime import datetime, timedelta

#import sqlite3
#import mysql.connector
#from mysql.connector import Error
#import re, nltk
import nltk
import numpy as np
from nltk.stem.porter import PorterStemmer
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
import nltk
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
#from sklearn.naive_bayes import MultinomialNB
#from sklearn.linear_model import LogisticRegression
#from sklearn import metrics
# Machine Learning
from sklearn.model_selection import train_test_split
#from sklearn.model_selection import cross_val_score
#from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
#from sklearn.naive_bayes import GaussianNB
#from sklearn.svm import LinearSVC
#from sklearn.model_selection import cross_val_predict
#from sklearn.metrics import confusion_matrix
#from sklearn.metrics import precision_score, recall_score
#from sklearn.metrics import f1_score
#from sklearn.metrics import precision_recall_curve
#from sklearn.metrics import roc_curve
#from sklearn.metrics import roc_auc_score
#from sklearn.metrics import classification_report
nltk.download('stopwords')
lemmatizer = WordNetLemmatizer()
stemmer = PorterStemmer()
english_stops = stopwords.words('english')
import numpy as np
# Connection variables

    # Connection string
cnxn = po.connect('Driver={SQL Server Native Client 11.0};SERVER=' +
server+';DATABASE='+database+';UID='+username+';PWD=' + password)
cursor = cnxn.cursor()

storedProc = " EXEC EMS.SpGetAccountIdListIdTimeDifferenceForAnalysis"
result=pd.read_sql_query(storedProc,cnxn)
#cursor.execute(storedProc)
df2=pd.DataFrame(result,columns=['ACCOUNTID','LISTID'])
print(df2)

#median
def my_median(sample):
    n = len(sample)
    index = n // 2
     # Sample with an odd number of observations
    if n % 2:
         return sorted(sample)[index]
     # Sample with an even number of observations
    return sum(sorted(sample)[index - 1:index + 1]) / 2

for index,row in df2.iterrows():
    storedProc1 = "EXEC EMS.SpGetAggregateCampaignDataForAnalysis @AccountId="+str(row['ACCOUNTID'])+",@ListId="+str(row['LISTID'])+""
    result1=pd.read_sql_query(storedProc1,cnxn)
    #cursor.execute(storedProc1)
    df1=pd.DataFrame(result1,columns=['ListID',	'SegmentID',	'CampaignName','AccountID',	'CampaignSubject'	,'List'	,'Segment','Sent'	,'Delivered',	'Open',	'Click',	'Bounced',	'UniqueOpen',	'UniqueClick',	'Unsubscribe',	'Spam'	,'VirtualSpam',	'SendDate'])
    print(df1)
    data=df1
    data["Percentage_open"]=(pd.to_numeric(data['UniqueOpen']/data['Delivered']))*100
    data=data.sort_values("Percentage_open",axis=0,ascending=False)
    value_median=my_median(data["Percentage_open"])
#print(value_median)
    final_median=(20/100)*value_median
#final_median
    sd_median=value_median-final_median
    f=np.percentile(data["Percentage_open"], sd_median)
    data["Open_Percentage"]=np.where(data['Percentage_open']>=f,'1','0')

    from sklearn.feature_extraction.text import TfidfTransformer
    cv=TfidfVectorizer(analyzer='word',min_df=.005, max_df=.9,ngram_range=(2,3))
    review_tf = cv.fit_transform(data['CampaignSubject'])
    review_tf_nd = review_tf.toarray()
    df = pd.DataFrame(review_tf_nd, columns=cv.get_feature_names())
    print(df)
    model = pd.merge(data, df, left_index=True, right_index=True)
#file=model.to_csv('D:/new/result.csv')
    ml_model=model.drop(['ListID',	'SegmentID',	'CampaignName','AccountID',	'CampaignSubject'	,'List'	,'Segment','Sent'	,'Delivered',	'Open',	'Click',	'Bounced',	'UniqueOpen',	'UniqueClick',	'Unsubscribe',	'Spam'	,'VirtualSpam',	'SendDate','Percentage_open'],axis=1)
    print('hi')
#for i in model.columns:
    #print([i])
#ml_model=model.drop(["CampaignName"])
# Create X & y variables for Machine Learning
    X = ml_model.drop('Open_Percentage', axis=1)
    y = ml_model['Open_Percentage']
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state=0)
    def model(mod, model_name, x_train, y_train, x_test, y_test):
        mod.fit(x_train, y_train)
        print(model_name)

        #acc = cross_val_score(mod, X_train, y_train, scoring = "accuracy", cv = 5)
        #predictions = cross_val_predict(mod, X_train, y_train, cv = 5)
        #print("Accuracy:", round(acc.mean(),3))
        #cm = confusion_matrix(predictions, y_train)
        #print("Confusion Matrix:  \n", cm)
        #print("                    Classification Report \n",classification_report(predictions, y_train))

# 2. Random Forest Classifier
    ran = RandomForestClassifier(random_state=0)
    model(ran, "Random Forest Classifier", X_train, y_train, X_test, y_test)
# Compile arrays of columns (words) and feature importances
    fi = {'Words':ml_model.drop('Open_Percentage',axis=1).columns.tolist(),'Importance':ran.feature_importances_}

# Bung these into a dataframe, rank highest to lowest then slice top 20
    Importances = pd.DataFrame(fi).sort_values('Importance',ascending=False).head(20)
    data['wordsCount'] = data['CampaignSubject'].apply(lambda x: len(str(x).split(" ")))
    data['Date']=pd.to_datetime(data['SendDate'])
    data["SendDay"] = pd.to_datetime(data.Date, format="%Y/%m/%d").dt.day_name()
    data["SendMonth"] = pd.to_datetime(data.Date, format="%Y/%m/%d").dt.month
    data['hour'] = data['Date'].dt.hour
    group_words=data.groupby('wordsCount',as_index=False)["Percentage_open"].count()

    group_words=pd.DataFrame(group_words).sort_values(by=['Percentage_open'],ascending=False).head(10)
    group_day=data.groupby('SendDay',as_index=False)["Percentage_open"].count()
    group_day=pd.DataFrame(group_day).head(10)
    group_hour=data.groupby('hour',as_index=False)["Percentage_open"].count()

    group_hour=pd.DataFrame(group_hour).head(10)

    h=group_hour['hour'].to_list()
    h = str(h)[1:-1]
    h="".join(h.split())
    h="'{}'".format(h)

    w=group_words['wordsCount'].to_list()
    w=str(w)[1:-1]
    w="".join(w.split())
    w="'{}'".format(w)

    d=",".join(group_day['SendDay'])
    d="'{}'".format(d)
    words=','.join(Importances['Words'])
    words="'{}'".format(words)
    #store in sp
    hh=group_hour.values.tolist()
    hh=str(hh)
    import re
    import json
    dd=group_day[['SendDay','Percentage_open']]
    dd=dd.values.tolist()
    dd=json.dumps(dd)
    dd=re.sub(r'(?<!: )"(\S*?)"', '\\1', dd)
    dd="'{}'".format(dd)
    ff=group_hour.values.tolist()
    ff=str(ff)
    ff="'{}'".format(ff)

    ww=group_words.values.tolist()
    ww=str(ww)
    Importances=Importances['Words'].astype(str)

    sql="EXEC EMS.SpSaveCampaignAggregateAnalysisReport @AccountID="+str(row['ACCOUNTID'])+",@ListId="+str(row['LISTID'])+",@Days="+dd+",@Words="+words+",@Hours="+ff+",@WordCount="+w+""
    #cursor.execute(sql).commit()
    print(sql)

    #sql="EXEC EMS.SpSaveCampaignAggregateAnalysisReport @AccountID=?,@ListId=?,@Days=?,@Words=?,@Hours=?,WordCount=?"
    #params=(str(row['ACCOUNTID']),str(row['LISTID']),str(group_day),str(group_words),str(group_hour),str(Importances))


'''
'''

def kitchen():
    number_of_test_cases = int(input("Enter the number of test cases: "))
    for i in range(0,number_of_test_cases):
        number_of_students = int(input("Enter the number of students: "))
        end_time_of_cooking = list(map(int,input("Enter the times when they need to finish cooking (space separated): ").strip().split()))
        time_required_to_cook = list(map(int,input("Enter the time required to cook (space separated): ").strip().split()))
        available_time = 0
        count = 0
        while(count < number_of_students):
            if(available_time >= end_time_of_cooking[count]):
                available_time += time_required_to_cook[count]
                count += 1
            else:
                break
        print(count)
kitchen()


from datetime import datetime

class Error(Exception):
    pass

class RequestError(Error):
    def __init__(self, func, module, status):
        message = error_msg(f"RequestError: {func} - {module}", 200, status)
        add_log(message)
        self.message = message

class TimeRequestError(Error):
    def __init__(self, func, module, tries):
        message = error_msg(f"TimeRequestError: {func} - {module}", "", "Exceeded the limit of tries ({})".format(tries))
        add_log(message)
        self.message = message

class NotSubset(Error):
    def __init__(self, func, module, exp, rec):
        message = error_msg(f"NotSubset: {func} - {module}", exp, rec)
        add_log(message)
        self.message = message

def writeError(errorType, func, module, exp, rec):
        message = error_msg(str(errorType) + ": " + str(func) + " - " + str(module), exp, rec)
        add_log(message)
        return message

def error_msg(where, expected, received):
    where = str(where)
    expected = str(expected)
    received = str(received)

    date = datetime.now()
    date = date.strftime("%d/%m/%Y %H:%M:%S")
    msg = date + " Error local: " + where + "\n\tExpected: " + expected + "\n\tReceived: " + received + "\n"

    return msg

def add_log(msg):
    with open('log_file', 'a') as log:
        log.write(msg)


#!/usr/bin/python3
"""
Solution to the Log Parsing interview question. See `README.md` for description
"""

from sys import stdin
from string import Template
import signal
import re

class Log_Parser:
    """
    Parses standard input for lines that match a specific pattern:
        * <IP> - [<date>] "<request-type>" <status-code> <file-size>

    where <request-type> and a list of valid integers for <status-code> are
    inputted during instantiation.
    """

    def __init__(self, request, status_codes, print_frequency=10):
        """
        creates new instance of Log_Parser.

        Args:
            * request            (str): type of request to track
            * status_codes (list[int]): valid codes to track
            * print_frequency    (int): number of lines to read between prints

        Attributes:
            * total_size         (int): total size of all file sizes parsed
            * status_codes (dict(int: int)): frequency table for status codes
            * Pattern_Matcher    (re.Pattern obj): validates user input
        """
        # signal.signal(signal.SIGINT, self.sigint_handler)
        self.total_size = 0
        self.status_codes = {code: 0 for code in status_codes}
        self.print_frequency = print_frequency
        self.Pattern_Matcher = self.get_Pattern_Matcher(request)

        self.run()

    # def sigint_handler(self, signum, frame):
    #     """
    #     prints stats if a Keyboard Interruption (CTRL + C) occurs
    #     """
    #     self.print_stats()
    #     exit(0)

    def get_Pattern_Matcher(self, request):
        """
        Returns a Pattern object (from re module). Used to validate input lines
        """

        # This is the string pattern we want to match.
        template = r'^$ip - \[$date] "$request" $status_code $file_size\n'

        # re_8bit is a regex pattern that matches numbers between 1-255.
        # We use this value to build our regex pattern for an IP address
        re_8bit = r'\b(1\d\d|[1-9]\d?|2([0-4]\d|5[0-5]))\b'

        # These regular expressions complete the template string
        re_dict = {

            'ip': r'{0}\.{0}\.{0}\.{0}'.format(re_8bit),
            'date': r'\b\d{4}(-\d{2}){2} \d{2}(:\d{2}){2}\.\d{6}\b',

            # Escape characters from request string as needed
            'request': re.escape(request),

            # Include a regex group name to extract values from matched lines
            'status_code': r'(?P<status_code>\b\d{3}\b)',
            'file_size': r'(?P<file_size>\b\d+\b)'
        }

        # Create a pattern matcher for template string with all values sub'd
        return re.compile(Template(template).substitute(re_dict))

    def run(self):
        """
        Reads input line-by-line. If input matches pattern, then status
        code and file size are logged
        """
        count = 0
        for line in stdin:
            count += 1
            match = self.Pattern_Matcher.fullmatch(line)
            if match:
                self.total_size += int(match.group('file_size'))
                status_code = int(match.group('status_code'))
                if status_code in self.status_codes.keys():
                    self.status_codes[status_code] += 1
            if count == self.print_frequency:
                count = 0
                self.print_stats()
        self.print_stats()
        return (0)

    def print_stats(self):
        """
        prints status code frequency table and total file sizes for all
        evaluated lines
        """
        print('File size: {}'.format(self.total_size))
        for status_code, frequency in sorted(self.status_codes.items()):
            if frequency:
                print('{}: {}'.format(status_code, frequency))

if __name__ == '__main__':
    request = "GET /projects/260 HTTP/1.1"
    status_codes = [200, 301, 400, 401, 403, 404, 405, 500]
    Log_Parser(request, status_codes)


#! /usr/bin/env python
# -*- coding: utf-8 -*-
# __author__ = "Q1mi"
# Date: 2018/5/24
from django import template
from blog import models

register = template.Library()

@register.inclusion_tag("panel.html")
def show_panel(username):
    user = models.UserInfo.objects.filter(username=username).first()
    # 拿到当前用户的博客对象
    blog = user.blog
    # 方式一：查询当前站点的文章分类，在前端用连表查询取分类对应的文章数
    # category_list = models.Category.objects.filter(blog=blog)
    # 方式二：利用分组查询出每一个分类以及分类对应的文章数
    from django.db.models import Count
    category_list = models.Category.objects.filter(blog=blog).annotate(c=Count("article")).values("title", "c")
    print(category_list)
    # 查询当前站点的文章标签
    tag_list = models.Tag.objects.filter(blog=blog).annotate(c=Count("article")).values("title", "c")
    # 按年月归档文章
    archive_list = models.Article.objects.filter(user=user).extra(
        select={"create_ym": "DATE_FORMAT(create_time, '%%Y-%%m')"}
    ).values("create_ym").annotate(c=Count("nid")).values("create_ym", "c")

    return {
        "username": username,
        "category_list": category_list,
        "tag_list": tag_list,
        "archive_list": archive_list
    }


import torch
from helper import get_formatted_time
import helper

def train_model(model, criterion, optimizer, train_loader, valid_loader, epochs, run_on_gpu):
    """
    Train a model on a dataset.

    :param model: The model to train.
    :param criterion: The loss function.
    :param optimizer: The optimizer.
    :param train_loader: The training data loader.
    :param valid_loader: The validation data loader.
    :param epochs: The number of epochs to train for.
    :param run_on_gpu: If true, process function on GPU
    :return: The trained model.
    """

    print(helper.get_formatted_time(), "train_model start. run_on_gpu:", run_on_gpu)
    # Move the model to the GPU if available.
    if run_on_gpu and torch.cuda.is_available():
        print(helper.get_formatted_time(), "train_model before: device = torch.device('cuda')")
        device = torch.device("cuda")
        print(helper.get_formatted_time(), "train_model before: model.to(device)")
        model.to(device)
        print(helper.get_formatted_time(), "GPU is available and being used")
    else:
        device = torch.device("cpu")
        if run_on_gpu:
            print("GPU is not available, using CPU instead")
        else:
            print("using CPU as requested")

    print("\n*** train_model: epochs: {} ***\n".format(epochs))

    # Start training
    print("Start training time:", get_formatted_time())
    running_loss = 0
    for epoch in range(epochs):
        print(f"{get_formatted_time()} epoch {epoch + 1}/{epochs} start")
        model.train()
        for inputs, labels in train_loader:
            # Move the input and label tensors to the GPU.
            inputs, labels = inputs.to(device), labels.to(device)

            # Forward pass
            outputs = model(inputs)
            loss = criterion(outputs, labels)

            # Backward pass
            optimizer.zero_grad()
            # print("before loss.backward()")
            loss.backward()
            # print("after  loss.backward()")
            optimizer.step()
            running_loss += loss.item()

        # Evaluate the model on the validation set
        print(f"{get_formatted_time()} validation start")
        model.eval()
        with torch.no_grad():
            val_loss = 0
            val_accuracy = 0
            for inputs, labels in valid_loader:
                inputs, labels = inputs.to(device), labels.to(device)
                outputs = model(inputs)
                val_loss += criterion(outputs, labels).item()

                # Calculate accuracy
                ps = torch.exp(outputs)
                top_p, top_class = ps.topk(1, dim=1)
                equals = top_class == labels.view(*top_class.shape)
                val_accuracy += torch.mean(equals.type(torch.FloatTensor)).item()

        print(f"{get_formatted_time()} Epoch {epoch + 1}/{epochs}.. "
              f"Train loss: {running_loss / len(train_loader):.3f}.. "
              f"Validation loss: {val_loss / len(valid_loader):.3f}")
        print(f"Validation accuracy: {val_accuracy / len(valid_loader):.3f}")

    device = torch.device("cpu")
    model.to(device)
    print(f"{get_formatted_time()} End training time:")
    print(helper.get_formatted_time(), "train_model end")
    return model


import sys

with open("streets.txt","w") as f:
    f.write("""omg trop stylé omg omg omg
pleins de lignes
yeessssssss allooooooo
mdkcjziocjize xppzczdpoce
omg
omg
omg
omg
""")

def readfile(filename):
    '''pre : filename est un fichier
       post : retourne une liste comprenant tous les lignes du fichier'''
    with open(filename,"r") as f:
        text= f.read()
        l=text.split("\n")
        return l

def get_words(line):
    '''pre : line est une chaîne de caractères
       post : retourne une liste comprenant chaque mot de la chaîne sans aucune ponctuation'''
    l = list(line)
    a = " "
    for i in range(len(l)):
       if l[i] not in "azertyuiopmlkjhgfdsqwxcvbnAZERTYUIOPMLKJHGFDSQWXCVBN":
           l.insert(i, " ")
           del l[i+1]
       a += l[i]
    return a.lower().split()

def occ(word,line):
    '''pre : word et line sont des chaînes de caractères, word est un seul mot
       post : cherche le le nombre d'occurences du mot word dans la chaîne line'''
    words = get_words(line)
    occ = 0
    for i in words:
        if i == word:
            occ += 1
    return occ

def create_dict(l):
    '''pre : l est une liste comprenant des mot, leur position (ligne) et leur occurence dans le fichier
       post : retourne un dictionnaire comprenant les mots et un autre dictionnaire des position et des occurences'''
    dict={}
    d= {}

    for word,pos_occ in l:
        if word not in d:
            d[word] = [pos_occ]
        else:
            d[word].append(pos_occ)

    for word in d:
        a ={}
        for pos,occ in d[word]:
            a[pos] = occ
        dict[word] = a

    return dict

def create_index(filename):
    '''pre : filename est un fichier
       post : retourne un index : un dictionnaire comprenant tous les mots du fichier, leurs(s) position(s) et leur occurence'''
    txt = readfile(filename)
    l = []
    for line_numb in range(len(txt)):
        line = txt[line_numb]
        for word in get_words(line):
            l.append((word,(line_numb,occ(word,line))))
    return create_dict(l)

def get_lines(words, index):
    ''' pre : words est une liste de mot(s), index est un dictionnaire comprenant des mots, leurs(s) position(s) et leur occurence
        post : retourne une liste des positions des lignes dans lesquels tous les mots de la liste words sont présents'''
    l = []
    for line_word1 in index[words[0]].keys():
        count = 0
        for word in words:
            if line_word1 in index[word]:
                count += 1
        if count == len(words) and line_word1 not in l:
            l.append(line_word1)
    return l

"""
----------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------
"""

def test(did_pass):                                    #On définit d'abord une fonction "did_pass" que l'on va utiliser dans les autres fonctions test.

    """  Print the result of a test."""

    linenum = sys._getframe(1).f_lineno
    if did_pass:
        msg = "Test at line {0} ok.".format(linenum)
    else:
        msg = ("Test at line {0} FAILED.".format(linenum))
    print(msg)

def test_readfile():
    test(readfile("streets.txt") == ['omg trop stylé omg omg omg ', 'pleins de lignes', 'yeessssssss allooooooo', 'mdkcjziocjize xppzczdpoce', 'omg', 'omg', 'omg', 'omg', ''])

def test_get_words():

    test(get_words("l'otarie est une espece marine tres violente, le viol est courant chez cette espece") == ['l', 'otarie', 'est', 'une', 'espece', 'marine', 'tres', 'violente', 'le', 'viol', 'est', 'courant', 'chez', 'cette', 'espece'])
    test(get_words("j'adore la vie aujourd'hui")==['j', 'adore', 'la', 'vie', 'aujourd', 'hui'])
    test(get_words("Turmoil has engulfed the Galactic Republic.")==["turmoil", "has", "engulfed", "the", "galactic", "republic"])

def test_occ():
    test(occ("viol","l'otarie est une espece marine tres violente, le viol est courant chez cette espece")==1)
    test(occ("omg",'omg trop stylé omg omg omg ')==4)
    test(occ("gentillesse","la loutre est une espece marine tres violente, le viol est courant chez cette espece")==0)

def test_create_dict():
    test(create_dict([("avion",(1,0)),("avion",(2,2))])=={'avion': {1: 0, 2: 2}})

def test_create_index():
    test(create_index("streets.txt")=={'omg': {0: 4, 4: 1, 5: 1, 6: 1, 7: 1}, 'trop': {0: 1}, 'styl': {0: 1}, 'pleins': {1: 1}, 'de': {1: 1}, 'lignes': {1: 1}, 'yeessssssss': {2: 1}, 'allooooooo': {2: 1}, 'mdkcjziocjize': {3: 1}, 'xppzczdpoce': {3: 1}})

def test_get_lines():
    test(get_lines(["omg"],create_index("streets.txt"))==[0, 4, 5, 6, 7])
    test(get_lines(["programme"],create_index("READ ME.txt"))==[4])
    test(get_lines(["andru","amine"],create_index("READ ME.txt"))==[1])

test_readfile()
test_get_words()
test_occ()
test_create_dict()
test_create_index()
test_get_lines()


#!/usr/bin/python3

import datetime

try:
    from Crypto.Hash import keccak
    sha3_256 = lambda x: keccak.new(digest_bits=256, data=x).digest()
except:
    import _sha3
    sha3_256 = lambda x: _sha3.sha3_256(x).digest()

import sys
import binascii

registryStarted = 1493895600
launchLength = 4838400

def sha3(seed):
    return sha3_256(str(seed).encode('ascii'))

def getAllowedTime(name):
    hash = binascii.hexlify(sha3(name))
    return registryStarted + ((launchLength * (int(hash, 16) >> 128)) >> 128)

def main(args):
    utime = getAllowedTime(args[0])
    now = datetime.datetime.now()
    release = datetime.datetime.fromtimestamp(utime)
    if (release < now):
        print("AVAILABLE NOW")
    else:
        print("Available", release.strftime("%B %d %H:%M:%S"))
        print("Remaining:", str(release - now))

if __name__ == "__main__":
    main(sys.argv[1:])


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import json
import importlib
from django.views import View
from django.http import JsonResponse
from utils.response import BaseResponse
from django.shortcuts import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

from utils import auth
from api import config
from repository import models
from api.service import asset

class LimitView(View):
    def dispatch(self, request, *args, **kwargs):
        return super(LimitView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        response = BaseResponse()

        name = kwargs.get('n1', None)
        if name:
            try:
                result = models.AuthInfo.objects.filter(username=name, status=2).values('username', 'ip', 'hostname', 'rank')
                response.data = list(result)
                response.status = True
                return JsonResponse(response.__dict__)
            except Exception as e:
                response.error = "Didn't find %s" % name
                response.status = False
                return JsonResponse(response.__dict__)

        result = models.AuthInfo.objects.all().values('username', 'ip', 'hostname', 'rank', 'status')
        # result = models.AuthInfo.objects.all()
        response.data = list(result)
        response.status = True
        return JsonResponse(response.__dict__)

class AssetView(View):
    # @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(AssetView, self).dispatch(request, *args, **kwargs)

    # @method_decorator(auth.api_auth)
    def get(self, request, *args, **kwargs):
        """
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # appid = request.META.get(['HTTP_APPID'], None)
        # print(appid)
        # test = {'user': '用户名', 'pwd': '密码'}
        # result = json.dumps(test,ensure_ascii=True)
        # result = json.dumps(test,ensure_ascii=False)
        # return HttpResponse(result)

        # test = {'user': '用户名', 'pwd': '密码'}
        # result = json.dumps(test,ensure_ascii=True)
        # result = json.dumps(test,ensure_ascii=False)
        # return HttpResponse(result,content_type='application/json')

        # test = {'user': '用户名', 'pwd': '密码'}
        # return JsonResponse(test, json_dumps_params={"ensure_ascii": False})
        from django.db.models import Q

        # response = asset.get_untreated_servers()
        response = BaseResponse()

        # print(kwargs)
        b1 = kwargs.get('b1', None)
        b2 = kwargs.get('b2', None)
        b3 = kwargs.get('b3', None)
        if b1:
            try:
                b1_id = models.BusinessOne.objects.filter(name=kwargs['b1']).first().id
                if b2:
                    try:
                        b2_id = models.BusinessTwo.objects.filter(name=kwargs['b2']).first().id
                        if b3:
                            try:
                                b3_id = models.BusinessThree.objects.filter(name=kwargs['b3']).first().id

                                condition = Q()
                                con_business_1 = Q()
                                con_business_1.children.append(('business_1', b1_id))
                                con_business_2 = Q()
                                con_business_2.children.append(('business_2', b2_id))
                                con_business_3 = Q()
                                con_business_3.children.append(('business_3', b3_id))

                                condition.add(con_business_1, 'AND')
                                condition.add(con_business_2, 'AND')
                                condition.add(con_business_3, 'AND')

                                result = models.Asset.objects.filter(condition).values('host_ip', 'host_name', 'business_2__name')
                                response.data = list(result)
                                response.status = True
                                return JsonResponse(response.__dict__)
                            except Exception as e:
                                response.error = "Didn't find %s" % kwargs['b3']
                                response.status = False
                                return JsonResponse(response.__dict__)
                        print(b2_id)
                        condition = Q()
                        con_business_1 = Q()
                        con_business_1.children.append(('business_1', b1_id))
                        con_business_2 = Q()
                        con_business_2.children.append(('business_2', b2_id))

                        condition.add(con_business_1, 'AND')
                        condition.add(con_business_2, 'AND')

                        result = models.Asset.objects.filter(condition).values('host_ip', 'host_name', 'business_2__name')
                        response.data = list(result)
                        response.status = True
                        return JsonResponse(response.__dict__)
                    except Exception as e:
                        response.error = "Didn't find %s" % kwargs['b2']
                        response.status = False
                        return JsonResponse(response.__dict__)

                print(b1_id)
                condition = Q()
                con_business_1 = Q()
                con_business_1.children.append(('business_1', b1_id))

                condition.add(con_business_1, 'AND')

                result = models.Asset.objects.filter(condition).values('host_ip')
                response.data = list(result)
                response.status = True
                return JsonResponse(response.__dict__)

            except Exception as e:
                response.error = "Didn't find %s" % kwargs['b1']
                response.status = False
                return JsonResponse(response.__dict__)
        result = models.Asset.objects.all().values('host_ip')
        response.data = list(result)
        response.status = True

        return JsonResponse(response.__dict__)

    @method_decorator(auth.api_auths)
    def post(self, request, *args, **kwargs):
        """
        更新或者添加资产信息
        :param request:
        :param args:
        :param kwargs:
        :return: 1000 成功;1001 接口授权失败;1002 数据库中资产不存在
        """

        server_info = json.loads(request.body.decode('utf-8'))
        server_info = json.loads(server_info)
        new_ip = server_info['docker']

        host_ip = models.Asset.objects.filter(host_ip=new_ip).count()
        if host_ip:
            try:
                models.Asset.objects.create(host_ip=new_ip, host_name='a0-docker-%s' % new_ip, host_status=2,
                                            host_item=1, host_type=5, host_cpu=2, host_memory=2, business_1_id=1,
                                            bussiness_2_id=1, business_3_id=1)
            except Exception as e:
                ret = {'code': 1000, 'message': '[%s]添加失败...%s' % (new_ip, e)}
                return JsonResponse(ret)
            ret = {'code': 1002, 'message': '[%s]IP已经存在！' % new_ip}
        else:
            ret = {'code': 1000, 'message': '[%s]添加成功！' % new_ip}
        #
        # server_obj = models.Server.objects.filter(hostname=hostname).select_related('asset').first()
        # if not server_obj:
        #     ret['code'] = 1002
        #     ret['message'] = '[%s]资产不存在' % hostname
        #     return JsonResponse(ret)
        #
        # for k, v in config.PLUGINS_DICT.items():
        #     module_path, cls_name = v.rsplit('.', 1)
        #     cls = getattr(importlib.import_module(module_path), cls_name)
        #     response = cls.process(server_obj, server_info, None)
        #     if not response.status:
        #         ret['code'] = 1003
        #         ret['message'] = "[%s]资产更新异常" % hostname
        #     if hasattr(cls, 'update_last_time'):
        #         cls.update_last_time(server_obj, None)

        return JsonResponse(ret)

class ReleaseView(View):
    def dispatch(self, request, *args, **kwargs):
        return super(ReleaseView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        response = BaseResponse()

        name = kwargs.get('n1', None)
        if name:
            try:
                result = models.AuthInfo.objects.filter(username=name, status=2).values('username', 'ip', 'hostname', 'rank')
                response.data = list(result)
                response.status = True
                return JsonResponse(response.__dict__)
            except Exception as e:
                response.error = "Didn't find %s" % name
                response.status = False
                return JsonResponse(response.__dict__)

        result = models.ReleaseTask.objects.all().values('username', 'ip', 'hostname', 'rank', 'status')
        # result = models.AuthInfo.objects.all()
        response.data = list(result)
        response.status = True
        return JsonResponse(response.__dict__)

    def post(self, request, *args, **kwargs):
        response = BaseResponse()

        n1 = json.loads(request.body.decode('utf-8'))
        n1 = json.loads(n1)

        r_id = n1.get('id', None)
        msg = n1.get('msg', None)

        # 上传包md5值
        md5 = n1.get('md5', None)
        if md5:
            print(md5)
            models.ReleaseTask.objects.filter(id=r_id).update(release_md5=md5)
            models.ReleaseLog.objects.create(release_id=r_id, release_msg=md5)
            # 发布任务成功上传
            response.status = True
            return JsonResponse(response.__dict__)

        print(r_id, msg)
        try:
            models.ReleaseLog.objects.create(release_id=r_id, release_msg=msg)
            response.status = True
        except Exception as e:
            response.status = False

        obj = models.ReleaseLog.objects.filter(release_time__gt='2017-05-19 05:00').first()
        print(obj.release_time)

        return JsonResponse(response.__dict__)