<commit_before>import numpy
import math

from UM.Math.Quaternion import Quaternion

## This class is a 4x4 homogenous matrix wrapper arround numpy.
#
# Heavily based (in most cases a straight copy with some refactoring) on the excellent
# 'library' Transformations.py created by Christoph Gohlke.
class Matrix(object):
    def __init__(self, data = numpy.identity(4,dtype=numpy.float32)):
        self._data = data

    def at(self, x, y):
        if(x >= 4 or y >= 4 or x < 0 or y < 0):
            raise IndexError
        return self._data[x,y]

    def setRow(self, index, value):
        if index < 0 or index > 3:
            raise IndexError()

        self._data[0, index] = value[0]
        self._data[1, index] = value[1]
        self._data[2, index] = value[2]
        self._data[3, index] = value[3]

    def setColumn(self, index, value):
        if index < 0 or index > 3:
            raise IndexError()

        self._data[index, 0] = value[0]
        self._data[index, 1] = value[1]
        self._data[index, 2] = value[2]
        self._data[index, 3] = value[3]

    def multiply(self, matrix):
        self._data = numpy.dot(self._data, matrix.getData())

    def preMultiply(self, matrix):
        self._data = numpy.dot(matrix.getData(),self._data)

    ##  Get raw data.
    #   \returns 4x4 numpy array
    def getData(self):
        return self._data.astype(numpy.float32)

    ##  Create a 4x4 identity matrix. This overwrites any existing data.
    def setToIdentity(self):
        self._data = numpy.identity(4,dtype=numpy.float32)

    ##  Invert the matrix
    def invert(self):
        self._data = numpy.linalg.inv(self._data)

    ##  Return a inverted copy of the matrix.
    #   \returns The invertex matrix.
    def getInverse(self):
        return Matrix(numpy.linalg.inv(self._data))

    ##  Return the transpose of the matrix.
    def getTransposed(self):
        m = Matrix(numpy.transpose(self._data))
        return m

    ##  Translate the matrix based on Vector.
    #   \param direction The vector by which the matrix needs to be translated.
    def translate(self, direction):
        translation_matrix = Matrix()
        translation_matrix.setByTranslation(direction)
        self.multiply(translation_matrix)

    ##  Set the matrix by translation vector. This overwrites any existing data.
    #   \param direction The vector by which the (unit) matrix needs to be translated.
    def setByTranslation(self, direction):
        M = numpy.identity(4,dtype=numpy.float32)
        M[:3, 3] = direction.getData()[:3]
        self._data = M

    def setTranslation(self, translation):
        self._data[:3, 3] = translation.getData()[:3]

    ##  Rotate the matrix based on rotation axis
    #   \param angle The angle by which matrix needs to be rotated.
    #   \param direction Axis by which the matrix needs to be rotated about.
    #   \param point Point where from where the rotation happens. If None, origin is used.
    def rotateByAxis(self, angle, direction, point = None):
        rotation_matrix = Matrix()
        rotation_matrix.setByRotationAxis(angle, direction, point)
        self.multiply(rotation_matrix)

    ##  Set the matrix based on rotation axis. This overwrites any existing data.
    #   \param angle The angle by which matrix needs to be rotated in radians.
    #   \param direction Axis by which the matrix needs to be rotated about.
    #   \param point Point where from where the rotation happens. If None, origin is used.
    def setByRotationAxis(self, angle, direction, point = None):
        sina = math.sin(angle)
        cosa = math.cos(angle)
        direction_data = self._unit_vector(direction.getData())
        # rotation matrix around unit vector
        R = numpy.diag([cosa, cosa, cosa])
        R += numpy.outer(direction_data, direction_data) * (1.0 - cosa)
        direction_data *= sina
        R += numpy.array([[ 0.0, -direction_data[2], direction_data[1]],
                        [ direction_data[2], 0.0, -direction_data[0]],
                        [-direction_data[1], direction_data[0], 0.0]],dtype=numpy.float32)
        M = numpy.identity(4)
        M[:3, :3] = R
        if point is not None:
            # rotation not around origin
            point = numpy.array(point[:3], dtype=numpy.float32, copy=False)
            M[:3, 3] = point - numpy.dot(R, point)
        self._data = M

    ##  Scale the matrix by factor wrt origin & direction.
    #   \param factor The factor by which to scale
    #   \param origin From where does the scaling need to be done
    #   \param direction In what direction is the scaling (if None, it's uniform)
    def scaleByFactor(self, factor, origin = None, direction = None):
        scale_matrix = Matrix()
        scale_matrix.setByScaleFactor(factor, origin, direction)
        self.multiply(scale_matrix)

    ##  Set the matrix by scale by factor wrt origin & direction. This overwrites any existing data
    #   \param factor The factor by which to scale
    #   \param origin From where does the scaling need to be done
    #   \param direction In what direction is the scaling (if None, it's uniform)
    def setByScaleFactor(self, factor, origin = None, direction = None):
        if direction is None:
            # uniform scaling
            M = numpy.diag([factor, factor, factor, 1.0])
            if origin is not None:
                M[:3, 3] = origin[:3]
                M[:3, 3] *= 1.0 - factor
        else:
            # nonuniform scaling
            direction_data = direction.getData()
            factor = 1.0 - factor
            M = numpy.identity(4,dtype=numpy.float32)
            M[:3, :3] -= factor * numpy.outer(direction_data, direction_data)
            if origin is not None:
                M[:3, 3] = (factor * numpy.dot(origin[:3], direction_data)) * direction_data
        self._data = M

    ##  Set the matrix by proving a quaternion. This overwrites any existing data
    #   \param quaternion The quaternion used to set the matrix data.
    def setByQuaternion(self, quaternion):
        q = numpy.array(quaternion.getData(), dtype=numpy.float32, copy=True)
        n = numpy.dot(q, q)
        if n < Quaternion.EPS:
            return numpy.identity(4)
        q *= math.sqrt(2.0 / n)
        q = numpy.outer(q, q)
        self._data =  numpy.array([
            [1.0-q[2, 2]-q[3, 3],     q[1, 2]-q[3, 0],     q[1, 3]+q[2, 0], 0.0],
            [    q[1, 2]+q[3, 0], 1.0-q[1, 1]-q[3, 3],     q[2, 3]-q[1, 0], 0.0],
            [    q[1, 3]-q[2, 0],     q[2, 3]+q[1, 0], 1.0-q[1, 1]-q[2, 2], 0.0],
            [                0.0,                 0.0,                 0.0, 1.0]],
            dtype=numpy.float32)

    ##  Set the matrix to an orthographic projection. This overwrites any existing data.
    #   \param left The left edge of the projection
    #   \param right The right edge of the projection
    #   \param top The top edge of the projection
    #   \param bottom The bottom edge of the projection
    #   \param near The near plane of the projection
    #   \param far The far plane of the projection
    def setOrtho(self, left, right, bottom, top, near, far):
        self.setToIdentity()
        self._data[0, 0] = 2 / (right - left)
        self._data[1, 1] = 2 / (top - bottom)
        self._data[2, 2] = -2 / (far - near)
        self._data[3, 0] = -((right + left) / (right - left))
        self._data[3, 1] = -((top + bottom) / (top - bottom))
        self._data[3, 2] = -((far + near) / (far - near))

    ##  Set the matrix to a perspective projection. This overwrites any existing data.
    #   \param fovy Field of view in the Y direction
    #   \param aspect The aspect ratio
    #   \param near Distance to the near plane
    #   \param far Distance to the far plane
    def setPerspective(self, fovy, aspect, near, far):
        self.setToIdentity()

        f = math.cos(math.radians(fovy) / 2) / math.sin(math.radians(fovy) / 2)

        self._data[0, 0] = f / aspect
        self._data[1, 1] = f
        self._data[2, 2] = (far + near)/(near - far)
        self._data[2, 3] = -1
        self._data[3, 2] = (2 * far * near)/(near - far)

    def _unit_vector(self, data, axis=None, out=None):
        """Return ndarray normalized by length, i.e. Euclidean norm, along axis.

        >>> v0 = numpy.random.random(3)
        >>> v1 = unit_vector(v0)
        >>> numpy.allclose(v1, v0 / numpy.linalg.norm(v0))
        True
        >>> v0 = numpy.random.rand(5, 4, 3)
        >>> v1 = unit_vector(v0, axis=-1)
        >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=2)), 2)
        >>> numpy.allclose(v1, v2)
        True
        >>> v1 = unit_vector(v0, axis=1)
        >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=1)), 1)
        >>> numpy.allclose(v1, v2)
        True
        >>> v1 = numpy.empty((5, 4, 3))
        >>> unit_vector(v0, axis=1, out=v1)
        >>> numpy.allclose(v1, v2)
        True
        >>> list(unit_vector([]))
        []
        >>> list(unit_vector([1]))
        [1.0]

        """
        if out is None:
            data = numpy.array(data, dtype=numpy.float32, copy=True)
            if data.ndim == 1:
                data /= math.sqrt(numpy.dot(data, data))
                return data
        else:
            if out is not data:
                out[:] = numpy.array(data, copy=False)
            data = out
        length = numpy.atleast_1d(numpy.sum(data*data, axis))
        numpy.sqrt(length, length)
        if axis is not None:
            length = numpy.expand_dims(length, axis)
        data /= length
        if out is None:
            return data

<commit_msg>Implement __repr__ in Matrix<commit_after>import numpy
import math

from UM.Math.Quaternion import Quaternion

## This class is a 4x4 homogenous matrix wrapper arround numpy.
#
# Heavily based (in most cases a straight copy with some refactoring) on the excellent
# 'library' Transformations.py created by Christoph Gohlke.
class Matrix(object):
    def __init__(self, data = numpy.identity(4,dtype=numpy.float32)):
        self._data = data

    def at(self, x, y):
        if(x >= 4 or y >= 4 or x < 0 or y < 0):
            raise IndexError
        return self._data[x,y]

    def setRow(self, index, value):
        if index < 0 or index > 3:
            raise IndexError()

        self._data[0, index] = value[0]
        self._data[1, index] = value[1]
        self._data[2, index] = value[2]
        self._data[3, index] = value[3]

    def setColumn(self, index, value):
        if index < 0 or index > 3:
            raise IndexError()

        self._data[index, 0] = value[0]
        self._data[index, 1] = value[1]
        self._data[index, 2] = value[2]
        self._data[index, 3] = value[3]

    def multiply(self, matrix):
        self._data = numpy.dot(self._data, matrix.getData())

    def preMultiply(self, matrix):
        self._data = numpy.dot(matrix.getData(),self._data)

    ##  Get raw data.
    #   \returns 4x4 numpy array
    def getData(self):
        return self._data.astype(numpy.float32)

    ##  Create a 4x4 identity matrix. This overwrites any existing data.
    def setToIdentity(self):
        self._data = numpy.identity(4,dtype=numpy.float32)

    ##  Invert the matrix
    def invert(self):
        self._data = numpy.linalg.inv(self._data)

    ##  Return a inverted copy of the matrix.
    #   \returns The invertex matrix.
    def getInverse(self):
        return Matrix(numpy.linalg.inv(self._data))

    ##  Return the transpose of the matrix.
    def getTransposed(self):
        m = Matrix(numpy.transpose(self._data))
        return m

    ##  Translate the matrix based on Vector.
    #   \param direction The vector by which the matrix needs to be translated.
    def translate(self, direction):
        translation_matrix = Matrix()
        translation_matrix.setByTranslation(direction)
        self.multiply(translation_matrix)

    ##  Set the matrix by translation vector. This overwrites any existing data.
    #   \param direction The vector by which the (unit) matrix needs to be translated.
    def setByTranslation(self, direction):
        M = numpy.identity(4,dtype=numpy.float32)
        M[:3, 3] = direction.getData()[:3]
        self._data = M

    def setTranslation(self, translation):
        self._data[:3, 3] = translation.getData()[:3]

    ##  Rotate the matrix based on rotation axis
    #   \param angle The angle by which matrix needs to be rotated.
    #   \param direction Axis by which the matrix needs to be rotated about.
    #   \param point Point where from where the rotation happens. If None, origin is used.
    def rotateByAxis(self, angle, direction, point = None):
        rotation_matrix = Matrix()
        rotation_matrix.setByRotationAxis(angle, direction, point)
        self.multiply(rotation_matrix)

    ##  Set the matrix based on rotation axis. This overwrites any existing data.
    #   \param angle The angle by which matrix needs to be rotated in radians.
    #   \param direction Axis by which the matrix needs to be rotated about.
    #   \param point Point where from where the rotation happens. If None, origin is used.
    def setByRotationAxis(self, angle, direction, point = None):
        sina = math.sin(angle)
        cosa = math.cos(angle)
        direction_data = self._unit_vector(direction.getData())
        # rotation matrix around unit vector
        R = numpy.diag([cosa, cosa, cosa])
        R += numpy.outer(direction_data, direction_data) * (1.0 - cosa)
        direction_data *= sina
        R += numpy.array([[ 0.0, -direction_data[2], direction_data[1]],
                        [ direction_data[2], 0.0, -direction_data[0]],
                        [-direction_data[1], direction_data[0], 0.0]],dtype=numpy.float32)
        M = numpy.identity(4)
        M[:3, :3] = R
        if point is not None:
            # rotation not around origin
            point = numpy.array(point[:3], dtype=numpy.float32, copy=False)
            M[:3, 3] = point - numpy.dot(R, point)
        self._data = M

    ##  Scale the matrix by factor wrt origin & direction.
    #   \param factor The factor by which to scale
    #   \param origin From where does the scaling need to be done
    #   \param direction In what direction is the scaling (if None, it's uniform)
    def scaleByFactor(self, factor, origin = None, direction = None):
        scale_matrix = Matrix()
        scale_matrix.setByScaleFactor(factor, origin, direction)
        self.multiply(scale_matrix)

    ##  Set the matrix by scale by factor wrt origin & direction. This overwrites any existing data
    #   \param factor The factor by which to scale
    #   \param origin From where does the scaling need to be done
    #   \param direction In what direction is the scaling (if None, it's uniform)
    def setByScaleFactor(self, factor, origin = None, direction = None):
        if direction is None:
            # uniform scaling
            M = numpy.diag([factor, factor, factor, 1.0])
            if origin is not None:
                M[:3, 3] = origin[:3]
                M[:3, 3] *= 1.0 - factor
        else:
            # nonuniform scaling
            direction_data = direction.getData()
            factor = 1.0 - factor
            M = numpy.identity(4,dtype=numpy.float32)
            M[:3, :3] -= factor * numpy.outer(direction_data, direction_data)
            if origin is not None:
                M[:3, 3] = (factor * numpy.dot(origin[:3], direction_data)) * direction_data
        self._data = M

    ##  Set the matrix by proving a quaternion. This overwrites any existing data
    #   \param quaternion The quaternion used to set the matrix data.
    def setByQuaternion(self, quaternion):
        q = numpy.array(quaternion.getData(), dtype=numpy.float32, copy=True)
        n = numpy.dot(q, q)
        if n < Quaternion.EPS:
            return numpy.identity(4)
        q *= math.sqrt(2.0 / n)
        q = numpy.outer(q, q)
        self._data =  numpy.array([
            [1.0-q[2, 2]-q[3, 3],     q[1, 2]-q[3, 0],     q[1, 3]+q[2, 0], 0.0],
            [    q[1, 2]+q[3, 0], 1.0-q[1, 1]-q[3, 3],     q[2, 3]-q[1, 0], 0.0],
            [    q[1, 3]-q[2, 0],     q[2, 3]+q[1, 0], 1.0-q[1, 1]-q[2, 2], 0.0],
            [                0.0,                 0.0,                 0.0, 1.0]],
            dtype=numpy.float32)

    ##  Set the matrix to an orthographic projection. This overwrites any existing data.
    #   \param left The left edge of the projection
    #   \param right The right edge of the projection
    #   \param top The top edge of the projection
    #   \param bottom The bottom edge of the projection
    #   \param near The near plane of the projection
    #   \param far The far plane of the projection
    def setOrtho(self, left, right, bottom, top, near, far):
        self.setToIdentity()
        self._data[0, 0] = 2 / (right - left)
        self._data[1, 1] = 2 / (top - bottom)
        self._data[2, 2] = -2 / (far - near)
        self._data[3, 0] = -((right + left) / (right - left))
        self._data[3, 1] = -((top + bottom) / (top - bottom))
        self._data[3, 2] = -((far + near) / (far - near))

    ##  Set the matrix to a perspective projection. This overwrites any existing data.
    #   \param fovy Field of view in the Y direction
    #   \param aspect The aspect ratio
    #   \param near Distance to the near plane
    #   \param far Distance to the far plane
    def setPerspective(self, fovy, aspect, near, far):
        self.setToIdentity()

        f = math.cos(math.radians(fovy) / 2) / math.sin(math.radians(fovy) / 2)

        self._data[0, 0] = f / aspect
        self._data[1, 1] = f
        self._data[2, 2] = (far + near)/(near - far)
        self._data[2, 3] = -1
        self._data[3, 2] = (2 * far * near)/(near - far)

    def _unit_vector(self, data, axis=None, out=None):
        """Return ndarray normalized by length, i.e. Euclidean norm, along axis.

        >>> v0 = numpy.random.random(3)
        >>> v1 = unit_vector(v0)
        >>> numpy.allclose(v1, v0 / numpy.linalg.norm(v0))
        True
        >>> v0 = numpy.random.rand(5, 4, 3)
        >>> v1 = unit_vector(v0, axis=-1)
        >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=2)), 2)
        >>> numpy.allclose(v1, v2)
        True
        >>> v1 = unit_vector(v0, axis=1)
        >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=1)), 1)
        >>> numpy.allclose(v1, v2)
        True
        >>> v1 = numpy.empty((5, 4, 3))
        >>> unit_vector(v0, axis=1, out=v1)
        >>> numpy.allclose(v1, v2)
        True
        >>> list(unit_vector([]))
        []
        >>> list(unit_vector([1]))
        [1.0]

        """
        if out is None:
            data = numpy.array(data, dtype=numpy.float32, copy=True)
            if data.ndim == 1:
                data /= math.sqrt(numpy.dot(data, data))
                return data
        else:
            if out is not data:
                out[:] = numpy.array(data, copy=False)
            data = out
        length = numpy.atleast_1d(numpy.sum(data*data, axis))
        numpy.sqrt(length, length)
        if axis is not None:
            length = numpy.expand_dims(length, axis)
        data /= length
        if out is None:
            return data

    def __repr__(self):
        return "Matrix( {0} )".format(self._data)

<|endoftext|>


<commit_before>##### This only works with python2

import heapq
import sys
import re
import time

# global for logfile
recordFile = ''

def astar(start, h, c, trans, isFinal):
  q = [(c(start) + h(start), start)]
  heapq.heapify(q)
  seen = set([start])

  while True:
    (cost, s) = heapq.heappop(q)

    if isFinal(s):
      return s

    newstates = trans(s)
    for new in newstates:
      if not new in seen:
        seen.add(new)
        heapq.heappush(q, (c(new) + h(new), new))

def cost(state, standings):
  c = 0
  for matchup in state:
    for i in xrange(len(matchup)-1):
      c += standings[matchup[i]][1] - standings[matchup[i+1]][1]
  return c

def heuristic(state, standings, playersPerGame):
  h = 0
  addedIdxs = set()
  for matchup in state:
    for i in xrange(len(matchup)):
      addedIdxs.add(matchup[i])

  rankList = []
  for i in xrange(len(standings)):
    if not i in addedIdxs:
      rankList.append(standings[i][1])

  for i in xrange(0, len(rankList), playersPerGame):
    for j in xrange(i, i+playersPerGame-1):
      h += rankList[j] - rankList[j+1]

  return h

def isFinalState(state, numberOfGames):
  if len(state) < numberOfGames:
    return False
  return True

def generateNextStates(state, possibleMatchups):
  allowedMatchups = set()
  for matchup in possibleMatchups:
    allowed = True
    for stateMatchup in state:
      for i in matchup:
        if i in stateMatchup:
          allowed = False
          break
      if not allowed:
        break
    if allowed:
      allowedMatchups.add(matchup)

  return map(lambda newMatchup: state | frozenset([newMatchup]), allowedMatchups)

def getPossibleMatchups(standings, constraints, playersPerGame):
  matchups = []

  for i in xrange(len(standings)):
    (playerID, points) = standings[i]
    matchups.append(tuple([i]))

  currentPlayers = 1
  while currentPlayers < playersPerGame:
    newMatchups = []
    for i in xrange(len(matchups)):
      matchup = matchups[i]
      lastPlayerIdx = matchup[currentPlayers-1]
      for j in xrange(lastPlayerIdx+1, len(standings)):
        potentialPlayerID = standings[j][0]
        canAddPlayer = True
        for b in xrange(len(matchup)):
          playerIdx = matchup[b]
          playerID = standings[playerIdx][0]
          if (playerID, potentialPlayerID) in constraints or (potentialPlayerID, playerID) in constraints:
            canAddPlayer = False
            break
        if canAddPlayer:
          newMatchups.append(matchup + (j,))
    matchups = newMatchups
    currentPlayers += 1
  return matchups

def getNextRoundGames(standings, constraints, playersPerGame, numberOfGames):
  possibleMatchups = getPossibleMatchups(standings, constraints, playersPerGame)

  start = frozenset()
  h = lambda state: heuristic(state, standings, playersPerGame)
  c = lambda state: cost(state, standings)
  trans = lambda state: generateNextStates(state, possibleMatchups)
  isFinal = lambda state: isFinalState(state, numberOfGames)
  best = astar(start, h, c, trans, isFinal)

  return map(lambda matchup: tuple(map(lambda idx: standings[idx][0], matchup)), best)

def updateConstraints(constraints, games):
  for game in games:
    for i in xrange(len(game)-1):
      if game[i].startswith('bye'):
        continue
      for j in xrange(i+1, len(game)):
        if game[j].startswith('bye'):
          continue
        if (game[i],game[j]) in constraints or (game[j],game[i]) in constraints:
          continue
        constraints.add((game[i],game[j]))

def checkStandingsInput(players, pointsGainedPerPlayer):

  ptsCorrect = ''

  while True:
    # Ask if the point selection is correct
    print("\n\n\tYou entered the following points: ")
    for i in xrange(len(players)):
      print("\t\t" + players[i] + ": " + str(pointsGainedPerPlayer[players[i]]))
    done = rec_raw_input("\tIs this correct: [y/n] ")

    # Hit enter without choice or choice was not y/n
    while done != 'y' and done != 'n':
      done = rec_raw_input("\n\t\tYou did not select 'y' or 'n' please try again: [y/n]")

    if done == 'y':
      break

    # If they need to update a player, loop for players to update
    while done != 'y':
      player = rec_raw_input("\n\tWhich player has an incorrect points?")
      newpts = rec_raw_input("\n\tEnter the new points for " + player + ": ")
      print("\n\tModifying " + player + "'s " + "points to: " + newpts)
      pointsGainedPerPlayer[player] = newpts
      done = rec_raw_input("\t\tAre you done modifying player points? [y/n]")

  return pointsGainedPerPlayer

def updateStandings(players, standings):
  pointsGainedPerPlayer = {}
  print('Points gathered:')

  # For each player collect the number of points
  for i in xrange(len(players)):
    pts = rec_raw_input("\n\t" + players[i] + ": ")
    while True:
      if re.match('\d+$', pts.strip()):
        break
      print("\n\t\tYour selection '" + pts + "' is not a number. Please enter again.")
      pts = rec_raw_input("\t"+ players[i] + ": ")

    pointsGainedPerPlayer[players[i]] = int(pts.strip())

  # Validate points
  pointsGainedPerPlayer = checkStandingsInput(players, pointsGainedPerPlayer)

  # TODO: Check for point distribution for correct values

  standings = map(lambda x: (x[0], x[1]+int(pointsGainedPerPlayer[x[0]])), standings)
  standings = sorted(standings,key=lambda x: x[1], reverse=True)
  return standings

def printGames(games):
  count = 0;
  for game in games:
    count += 1
    print('Game ' + str(count))
    for playerID in game:
      print('\t' + playerID)

def printStandings(standings):
  print('\nCurrent Results:')
  for standing in standings:
    print('\t' + standing[0] + ' --> ' + str(standing[1]))

def rec_raw_input(inStr):
  global recordFile
  input = raw_input(inStr)
  recordFile.write(input+"\n")
  return input

def main():

  # record user input for state saving
  global recordFile
  recordFile = open('/tmp/game_record.'+str(time.time()), 'w')

  players =  []
  numberOfPlayers = int(input("Number of players: "))
  for i in xrange(numberOfPlayers):
    players.append(rec_raw_input("\tPlayer " + str(i+1) + ": "))

  playersPerGame = int(rec_raw_input("\nNumber of players per game: "))

  numberOfByePlayers = 0
  if len(players) % playersPerGame != 0:
    for i in xrange(playersPerGame - len(players) % playersPerGame):
      numberOfPlayers += 1
      numberOfByePlayers += 1
      players.append('bye' + str(i+1))
  numberOfGames = len(players) / playersPerGame

  standings = map(lambda x: tuple([x,0]), players)

  constraints = set()
  for i in xrange(numberOfByePlayers-1):
    constraints.add(('bye' + str(i+1),'bye' + str(i+2)))

  numberOfRounds = int(rec_raw_input("\nNumber of rounds: "))

  for n in xrange(numberOfRounds):
    print('----- Round ' + str(n+1) + ' -----')
    games = getNextRoundGames(standings, constraints, playersPerGame, numberOfGames)
    printGames(games)
    updateConstraints(constraints, games)
    standings = updateStandings(players, standings)
    printStandings(standings)

if __name__ == '__main__':
  main()
<commit_msg>Fixed bug on a missing raw_input<commit_after>##### This only works with python2

import heapq
import sys
import re
import time

# global for logfile
recordFile = ''

def astar(start, h, c, trans, isFinal):
  q = [(c(start) + h(start), start)]
  heapq.heapify(q)
  seen = set([start])

  while True:
    (cost, s) = heapq.heappop(q)

    if isFinal(s):
      return s

    newstates = trans(s)
    for new in newstates:
      if not new in seen:
        seen.add(new)
        heapq.heappush(q, (c(new) + h(new), new))

def cost(state, standings):
  c = 0
  for matchup in state:
    for i in xrange(len(matchup)-1):
      c += standings[matchup[i]][1] - standings[matchup[i+1]][1]
  return c

def heuristic(state, standings, playersPerGame):
  h = 0
  addedIdxs = set()
  for matchup in state:
    for i in xrange(len(matchup)):
      addedIdxs.add(matchup[i])

  rankList = []
  for i in xrange(len(standings)):
    if not i in addedIdxs:
      rankList.append(standings[i][1])

  for i in xrange(0, len(rankList), playersPerGame):
    for j in xrange(i, i+playersPerGame-1):
      h += rankList[j] - rankList[j+1]

  return h

def isFinalState(state, numberOfGames):
  if len(state) < numberOfGames:
    return False
  return True

def generateNextStates(state, possibleMatchups):
  allowedMatchups = set()
  for matchup in possibleMatchups:
    allowed = True
    for stateMatchup in state:
      for i in matchup:
        if i in stateMatchup:
          allowed = False
          break
      if not allowed:
        break
    if allowed:
      allowedMatchups.add(matchup)

  return map(lambda newMatchup: state | frozenset([newMatchup]), allowedMatchups)

def getPossibleMatchups(standings, constraints, playersPerGame):
  matchups = []

  for i in xrange(len(standings)):
    (playerID, points) = standings[i]
    matchups.append(tuple([i]))

  currentPlayers = 1
  while currentPlayers < playersPerGame:
    newMatchups = []
    for i in xrange(len(matchups)):
      matchup = matchups[i]
      lastPlayerIdx = matchup[currentPlayers-1]
      for j in xrange(lastPlayerIdx+1, len(standings)):
        potentialPlayerID = standings[j][0]
        canAddPlayer = True
        for b in xrange(len(matchup)):
          playerIdx = matchup[b]
          playerID = standings[playerIdx][0]
          if (playerID, potentialPlayerID) in constraints or (potentialPlayerID, playerID) in constraints:
            canAddPlayer = False
            break
        if canAddPlayer:
          newMatchups.append(matchup + (j,))
    matchups = newMatchups
    currentPlayers += 1
  return matchups

def getNextRoundGames(standings, constraints, playersPerGame, numberOfGames):
  possibleMatchups = getPossibleMatchups(standings, constraints, playersPerGame)

  start = frozenset()
  h = lambda state: heuristic(state, standings, playersPerGame)
  c = lambda state: cost(state, standings)
  trans = lambda state: generateNextStates(state, possibleMatchups)
  isFinal = lambda state: isFinalState(state, numberOfGames)
  best = astar(start, h, c, trans, isFinal)

  return map(lambda matchup: tuple(map(lambda idx: standings[idx][0], matchup)), best)

def updateConstraints(constraints, games):
  for game in games:
    for i in xrange(len(game)-1):
      if game[i].startswith('bye'):
        continue
      for j in xrange(i+1, len(game)):
        if game[j].startswith('bye'):
          continue
        if (game[i],game[j]) in constraints or (game[j],game[i]) in constraints:
          continue
        constraints.add((game[i],game[j]))

def checkStandingsInput(players, pointsGainedPerPlayer):

  ptsCorrect = ''

  while True:
    # Ask if the point selection is correct
    print("\n\n\tYou entered the following points: ")
    for i in xrange(len(players)):
      print("\t\t" + players[i] + ": " + str(pointsGainedPerPlayer[players[i]]))
    done = rec_raw_input("\tIs this correct: [y/n] ")

    # Hit enter without choice or choice was not y/n
    while done != 'y' and done != 'n':
      done = rec_raw_input("\n\t\tYou did not select 'y' or 'n' please try again: [y/n]")

    if done == 'y':
      break

    # If they need to update a player, loop for players to update
    while done != 'y':
      player = rec_raw_input("\n\tWhich player has an incorrect points?")
      newpts = rec_raw_input("\n\tEnter the new points for " + player + ": ")
      print("\n\tModifying " + player + "'s " + "points to: " + newpts)
      pointsGainedPerPlayer[player] = newpts
      done = rec_raw_input("\t\tAre you done modifying player points? [y/n]")

  return pointsGainedPerPlayer

def updateStandings(players, standings):
  pointsGainedPerPlayer = {}
  print('Points gathered:')

  # For each player collect the number of points
  for i in xrange(len(players)):
    pts = rec_raw_input("\n\t" + players[i] + ": ")
    while True:
      if re.match('\d+$', pts.strip()):
        break
      print("\n\t\tYour selection '" + pts + "' is not a number. Please enter again.")
      pts = rec_raw_input("\t"+ players[i] + ": ")

    pointsGainedPerPlayer[players[i]] = int(pts.strip())

  # Validate points
  pointsGainedPerPlayer = checkStandingsInput(players, pointsGainedPerPlayer)

  # TODO: Check for point distribution for correct values

  standings = map(lambda x: (x[0], x[1]+int(pointsGainedPerPlayer[x[0]])), standings)
  standings = sorted(standings,key=lambda x: x[1], reverse=True)
  return standings

def printGames(games):
  count = 0;
  for game in games:
    count += 1
    print('Game ' + str(count))
    for playerID in game:
      print('\t' + playerID)

def printStandings(standings):
  print('\nCurrent Results:')
  for standing in standings:
    print('\t' + standing[0] + ' --> ' + str(standing[1]))

def rec_raw_input(inStr):
  global recordFile
  input = raw_input(inStr)
  recordFile.write(input+"\n")
  return input

def main():

  # record user input for state saving
  global recordFile
  recordFile = open('/tmp/game_record.'+str(time.time()), 'w')

  players =  []
  numberOfPlayers = int(rec_raw_input("Number of players: "))
  for i in xrange(numberOfPlayers):
    players.append(rec_raw_input("\tPlayer " + str(i+1) + ": "))

  playersPerGame = int(rec_raw_input("\nNumber of players per game: "))

  numberOfByePlayers = 0
  if len(players) % playersPerGame != 0:
    for i in xrange(playersPerGame - len(players) % playersPerGame):
      numberOfPlayers += 1
      numberOfByePlayers += 1
      players.append('bye' + str(i+1))
  numberOfGames = len(players) / playersPerGame

  standings = map(lambda x: tuple([x,0]), players)

  constraints = set()
  for i in xrange(numberOfByePlayers-1):
    constraints.add(('bye' + str(i+1),'bye' + str(i+2)))

  numberOfRounds = int(rec_raw_input("\nNumber of rounds: "))

  for n in xrange(numberOfRounds):
    print('----- Round ' + str(n+1) + ' -----')
    games = getNextRoundGames(standings, constraints, playersPerGame, numberOfGames)
    printGames(games)
    updateConstraints(constraints, games)
    standings = updateStandings(players, standings)
    printStandings(standings)

if __name__ == '__main__':
  main()
<|endoftext|>


<commit_before>from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import six
import numpy as np
import h5py
import tempfile
import uuid

from filestore.api import (insert_resource, insert_datum, retrieve,
                           register_handler, deregister_handler, db_disconnect,
                           db_connect)

import filestore.retrieve as fsr

from filestore.handlers import AreaDetectorHDF5Handler
from filestore.handlers import DummyAreaDetectorHandler
from filestore.handlers import HDFMapsSpectrumHandler as HDFM
from filestore.handlers import HDFMapsEnergyHandler as HDFE
from filestore.handlers import NpyFrameWise
from numpy.testing import assert_array_equal
import os
from itertools import product
from nose.tools import assert_true, assert_raises

from six.moves import range
db_name = str(uuid.uuid4())
conn = None

def setup():
    global conn
    db_disconnect()
    db_connect(db_name, 'localhost', 27017)

    register_handler('AD_HDF5', AreaDetectorHDF5Handler)

def teardown():
    deregister_handler('AD_HDF5')
    db_disconnect()
    # if we know about a connection, drop the database
    if conn:
        conn.drop_database(db_name)

class _with_file(object):
    # a base-class for testing which provides a temporary file for
    # I/O tests.  This class provides a setup function which creates
    # a temporary file (path stored in `self.filename`).  Sub-classes
    # should over-ride `_make_data` to fill the file with data for the test.
    def setup(self):
        with tempfile.NamedTemporaryFile(delete=False) as fn:
            self.filename = fn.name
        self._make_data()

    def teardown(self):
        os.unlink(self.filename)

    def _make_data(self):
        # sub-classes need to override this to put data into the test file
        pass

class test_np_FW(_with_file):
    def _make_data(self):
        N = 15
        filename = self.filename
        data = np.ones((N, 9, 8)) * np.arange(N).reshape(N, 1, 1)
        np.save(filename, data)
        # Insert the data records.
        resource_id = insert_resource('npy_FRAMEWISE', filename + '.npy', {})
        self.datum_ids = [str(uuid.uuid4()) for i in range(N)]
        for i, datum_id in enumerate(self.datum_ids):
            insert_datum(resource_id, datum_id, dict(frame_no=i))

    def test_retrival(self):
        with fsr.handler_context({'npy_FRAMEWISE': NpyFrameWise}):
            for i, datum_id in enumerate(self.datum_ids):
                data = retrieve(datum_id)
                known_data = i * np.ones((9, 8))
                assert_array_equal(data, known_data)

class test_AD_hdf5_files(_with_file):
    # test the HDF5 product emitted by the hdf5 plugin to area detector
    def _make_data(self):
        filename = self.filename
        with h5py.File(filename) as f:
            N = 5
            # Write the data.
            data = np.multiply.outer(np.arange(N), np.ones((2, 2)))
            f.create_dataset('/entry/data/data', data=data)

        # Insert the data records.
        resource_id = insert_resource('AD_HDF5', filename)
        self.datum_ids = [str(uuid.uuid4()) for i in range(N)]
        for i, datum_id in enumerate(self.datum_ids):
            insert_datum(resource_id, datum_id, dict(point_number=i))

    def test_AD_round_trip(self):

        # Retrieve the data.
        for i, datum_id in enumerate(self.datum_ids):
            data = retrieve(datum_id)
            known_data = i * np.ones((2, 2))
            assert_array_equal(data, known_data)

    def test_context_manager(self):
        # make sure context manager works
        with AreaDetectorHDF5Handler(self.filename) as hand:
            assert hand._file
            # also test double opening a handler
            hand.open()

    def test_open_close(self):

        hand = AreaDetectorHDF5Handler(self.filename)  # calls open()
        assert_true(hand._file is not None)
        hand.close()
        assert_true(hand._file is None)
        hand.open()
        assert_true(hand._file is not None)
        hand.close()
        assert_true(hand._file is None)

class test_maps_hdf5(_with_file):
    n_pts = 20
    N = 10
    M = 11

    # tests the MAPS handler (product specification from APS)
    def _make_data(self):
        self.th = np.linspace(0, 2*np.pi, self.n_pts)
        self.scale = np.arange(self.N*self.M)

        with h5py.File(self.filename, 'w') as f:
            # create a group for maps to hold the data
            mapsGrp = f.create_group('MAPS')
            # now set a comment
            mapsGrp.attrs['comments'] = 'MAPS group'

            entryname = 'mca_arr'
            comment = 'These are raw spectrum data.'
            sn = np.sin(self.th).reshape(self.n_pts, 1, 1)
            XY = self.scale.reshape(1, self.N, self.M)
            data = XY * sn
            ds_data = mapsGrp.create_dataset(entryname, data=data)
            ds_data.attrs['comments'] = comment

        # insert spectrum-wise resource and datum
        resource_id = insert_resource('hdf5_maps', self.filename,
                                      {'dset_path': 'mca_arr'})
        self.eids_spectrum = [str(uuid.uuid4()) for j in range(self.N*self.M)]

        for uid, (i, j) in zip(self.eids_spectrum,
                               product(range(self.N), range(self.M))):
            insert_datum(resource_id, uid, {'x': i, 'y': j})

        # insert plane-wise resource and datum
        resource_id = insert_resource('hdf5_planes', self.filename,
                                      {'dset_path': 'mca_arr'})
        self.eids_planes = [str(uuid.uuid4()) for j in range(self.n_pts)]

        for uid, n in zip(self.eids_planes, range(self.n_pts)):
            insert_datum(resource_id, uid, {'e_index': n})

    def test_maps_spectrum_round_trip(self):
        sn = np.sin(self.th)

        with fsr.handler_context({'hdf5_maps': HDFM}):
            for eid, sc in zip(self.eids_spectrum, self.scale):
                print(eid)
                data = retrieve(eid)
                assert_array_equal(data, sc * sn)

    def test_maps_plane_round_trip(self):
        base = self.scale.reshape(self.N, self.M)
        with fsr.handler_context({'hdf5_planes': HDFE}):
            for eid, v in zip(self.eids_planes, np.sin(self.th)):
                data = retrieve(eid)
                assert_array_equal(data, base * v)

    def test_closed_rasise(self):
        hand = HDFE(self.filename, 'mca_arr')
        hand.close()
        assert_raises(RuntimeError, hand, 0)

def _dummy_helper(n_pts, hand, kwargs):
    target_data = (np.ones((n_pts, 10, 10)) * np.nan).squeeze()

    assert_array_equal(target_data, hand(**kwargs))

def test_ADDummy():

    for n_pts in [1, 5]:
        hand = DummyAreaDetectorHandler(None, frame_per_point=n_pts, aadvark=5)
        for kw in [{}, {'a': 1}]:
            yield _dummy_helper, n_pts, hand, kw

def test_npyfw_fail():
    assert_raises(IOError, NpyFrameWise, 'aarvark_rises')
<commit_msg>TST: add tests for path only tiff handler<commit_after>from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import six
import numpy as np
import h5py
import tempfile
import uuid

from filestore.api import (insert_resource, insert_datum, retrieve,
                           register_handler, deregister_handler, db_disconnect,
                           db_connect)

import filestore.retrieve as fsr

from filestore.handlers import AreaDetectorHDF5Handler
from filestore.handlers import DummyAreaDetectorHandler
from filestore.handlers import HDFMapsSpectrumHandler as HDFM
from filestore.handlers import HDFMapsEnergyHandler as HDFE
from filestore.handlers import NpyFrameWise
from filestore.path_only_handlers import AreaDetectorTiffPathOnlyHandler
from numpy.testing import assert_array_equal
import os
from itertools import product
from nose.tools import assert_true, assert_raises, assert_equal

from six.moves import range
db_name = str(uuid.uuid4())
conn = None

def setup():
    global conn
    db_disconnect()
    db_connect(db_name, 'localhost', 27017)

    register_handler('AD_HDF5', AreaDetectorHDF5Handler)

def teardown():
    deregister_handler('AD_HDF5')
    db_disconnect()
    # if we know about a connection, drop the database
    if conn:
        conn.drop_database(db_name)

class _with_file(object):
    # a base-class for testing which provides a temporary file for
    # I/O tests.  This class provides a setup function which creates
    # a temporary file (path stored in `self.filename`).  Sub-classes
    # should over-ride `_make_data` to fill the file with data for the test.
    def setup(self):
        with tempfile.NamedTemporaryFile(delete=False) as fn:
            self.filename = fn.name
        self._make_data()

    def teardown(self):
        os.unlink(self.filename)

    def _make_data(self):
        # sub-classes need to override this to put data into the test file
        pass

class test_np_FW(_with_file):
    def _make_data(self):
        N = 15
        filename = self.filename
        data = np.ones((N, 9, 8)) * np.arange(N).reshape(N, 1, 1)
        np.save(filename, data)
        # Insert the data records.
        resource_id = insert_resource('npy_FRAMEWISE', filename + '.npy', {})
        self.datum_ids = [str(uuid.uuid4()) for i in range(N)]
        for i, datum_id in enumerate(self.datum_ids):
            insert_datum(resource_id, datum_id, dict(frame_no=i))

    def test_retrival(self):
        with fsr.handler_context({'npy_FRAMEWISE': NpyFrameWise}):
            for i, datum_id in enumerate(self.datum_ids):
                data = retrieve(datum_id)
                known_data = i * np.ones((9, 8))
                assert_array_equal(data, known_data)

class test_AD_hdf5_files(_with_file):
    # test the HDF5 product emitted by the hdf5 plugin to area detector
    def _make_data(self):
        filename = self.filename
        with h5py.File(filename) as f:
            N = 5
            # Write the data.
            data = np.multiply.outer(np.arange(N), np.ones((2, 2)))
            f.create_dataset('/entry/data/data', data=data)

        # Insert the data records.
        resource_id = insert_resource('AD_HDF5', filename)
        self.datum_ids = [str(uuid.uuid4()) for i in range(N)]
        for i, datum_id in enumerate(self.datum_ids):
            insert_datum(resource_id, datum_id, dict(point_number=i))

    def test_AD_round_trip(self):

        # Retrieve the data.
        for i, datum_id in enumerate(self.datum_ids):
            data = retrieve(datum_id)
            known_data = i * np.ones((2, 2))
            assert_array_equal(data, known_data)

    def test_context_manager(self):
        # make sure context manager works
        with AreaDetectorHDF5Handler(self.filename) as hand:
            assert hand._file
            # also test double opening a handler
            hand.open()

    def test_open_close(self):

        hand = AreaDetectorHDF5Handler(self.filename)  # calls open()
        assert_true(hand._file is not None)
        hand.close()
        assert_true(hand._file is None)
        hand.open()
        assert_true(hand._file is not None)
        hand.close()
        assert_true(hand._file is None)

class test_maps_hdf5(_with_file):
    n_pts = 20
    N = 10
    M = 11

    # tests the MAPS handler (product specification from APS)
    def _make_data(self):
        self.th = np.linspace(0, 2*np.pi, self.n_pts)
        self.scale = np.arange(self.N*self.M)

        with h5py.File(self.filename, 'w') as f:
            # create a group for maps to hold the data
            mapsGrp = f.create_group('MAPS')
            # now set a comment
            mapsGrp.attrs['comments'] = 'MAPS group'

            entryname = 'mca_arr'
            comment = 'These are raw spectrum data.'
            sn = np.sin(self.th).reshape(self.n_pts, 1, 1)
            XY = self.scale.reshape(1, self.N, self.M)
            data = XY * sn
            ds_data = mapsGrp.create_dataset(entryname, data=data)
            ds_data.attrs['comments'] = comment

        # insert spectrum-wise resource and datum
        resource_id = insert_resource('hdf5_maps', self.filename,
                                      {'dset_path': 'mca_arr'})
        self.eids_spectrum = [str(uuid.uuid4()) for j in range(self.N*self.M)]

        for uid, (i, j) in zip(self.eids_spectrum,
                               product(range(self.N), range(self.M))):
            insert_datum(resource_id, uid, {'x': i, 'y': j})

        # insert plane-wise resource and datum
        resource_id = insert_resource('hdf5_planes', self.filename,
                                      {'dset_path': 'mca_arr'})
        self.eids_planes = [str(uuid.uuid4()) for j in range(self.n_pts)]

        for uid, n in zip(self.eids_planes, range(self.n_pts)):
            insert_datum(resource_id, uid, {'e_index': n})

    def test_maps_spectrum_round_trip(self):
        sn = np.sin(self.th)

        with fsr.handler_context({'hdf5_maps': HDFM}):
            for eid, sc in zip(self.eids_spectrum, self.scale):
                print(eid)
                data = retrieve(eid)
                assert_array_equal(data, sc * sn)

    def test_maps_plane_round_trip(self):
        base = self.scale.reshape(self.N, self.M)
        with fsr.handler_context({'hdf5_planes': HDFE}):
            for eid, v in zip(self.eids_planes, np.sin(self.th)):
                data = retrieve(eid)
                assert_array_equal(data, base * v)

    def test_closed_rasise(self):
        hand = HDFE(self.filename, 'mca_arr')
        hand.close()
        assert_raises(RuntimeError, hand, 0)

def _dummy_helper(n_pts, hand, kwargs):
    target_data = (np.ones((n_pts, 10, 10)) * np.nan).squeeze()

    assert_array_equal(target_data, hand(**kwargs))

def test_ADDummy():

    for n_pts in [1, 5]:
        hand = DummyAreaDetectorHandler(None, frame_per_point=n_pts, aadvark=5)
        for kw in [{}, {'a': 1}]:
            yield _dummy_helper, n_pts, hand, kw

def test_npyfw_fail():
    assert_raises(IOError, NpyFrameWise, 'aarvark_rises')

def _test_tiff_path_only(path, fname, fpp):
    test = AreaDetectorTiffPathOnlyHandler(path, '%s%s_%6.6d.tiff', fname, fpp)
    template = '{}{}_{{:06d}}.tiff'.format(path, fname)
    for j in range(5):
        res = test(j)
        expected = [template.format(n) for n in range(j*fpp, (j+1)*fpp)]
        assert_equal(res, expected)

def test_tiff_path_handler():
    yield _test_tiff_path_only, '/foo/', 'baz', 1
    yield _test_tiff_path_only, '/foo/', 'baz', 5
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from os import path, environ
from flask import Flask, jsonify, abort
import yaml
import json
from glob import glob
import itertools
import urbanairship as ua
import redis
import datetime
import time
import uuid
import sys

app = Flask(__name__)
base_path = path.dirname(path.abspath(__file__))

ua_app_key = environ['UA_APP_KEY']
ua_master_secret = environ['UA_MASTER_SECRET']
airship = ua.Airship(ua_app_key, ua_master_secret)

class DateTimeSupportJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime.datetime):
            return o.isoformat()
        return super(DateTimeSupportJSONEncoder, self).default(o)

class Session:
    def __init__(self, title, name, room, type=None):
        self.title = title
        self.name = name
        self.room = room

    def to_json(self):
        return json.dumps(self.to_hash())

    def to_hash(self):
        return {'title': self.title, 'name': self.name, 'room': self.room,
                'type': 'session'}

class Notification:
    def __init__(self, uuid, message, url, created_at, image):
        self.uuid = uuid
        self.message = message
        self.url = url
        self.image = image
        self.created_at = created_at

    def key(self):
        return 'notification.{}'.format(self.uuid)

    def to_json(self):
        return json.dumps(self.to_hash())

    def to_hash(self):
        return {'uuid': self.uuid, 'message': self.message,
                'url': self.url, 'created_at': self.created_at,
                'image': self.image}

    @classmethod
    def loads(cls, json_str):
        d = json.loads(json_str)
        return Notification(**d)

class NotificationStore:
    key = 'notifications'

    def __init__(self):
        self.r = redis.from_url(environ.get('REDIS_URL'))

    def add_notification(self, notification):
        self.r.zadd(self.key, notification.key(), notification.created_at)
        self.r.set(notification.key(), notification.to_json())

    def fetch_notifications(self):
        keys = self.r.zrange(self.key, 0, 100, desc=True)
        if len(keys) == 0:
            return []
        notifications = self.r.mget(keys)
        print(keys, file=sys.stderr)
        print(notifications, file=sys.stderr)
        return map(lambda n: Notification.loads(n.decode('utf-8')),
                   notifications)

    def remove_all(self):
        self.r.delete(self.key)

store = NotificationStore()

def send_notification(message):
    now = datetime.datetime.now()
    timestamp = int(time.mktime(now.timetuple()))
    store.add_notification(Notification(str(uuid.uuid4()), message,
                                        'hoge.com', timestamp,
                                        'http://image.com'))
    try:
        push = airship.create_push()
        push.audience = ua.all_
        notification = ua.ios(alert=message,
                              extra={'url': 'https://google.com'})
        push.ios = notification
        push.device_types = ua.ios
        push.send()
    except:
        return False
    return True

@app.route('/remove-all')
def remove_all():
    store.remove_all()
    return 'done'

@app.route('/apns')
def apns_send():
    message = 'Hello world2'
    send_notification(message)
    push = airship.create_push()
    push.audience = ua.all_
    push.notification = ua.notification(alert=message)
    push.device_types = ua.all_
    push.send()
    # try:
    # except:
    #     return 'error'
    return 'success'

@app.route('/notifications')
def notifications_list():
    notifications = store.fetch_notifications()
    n = map(lambda n: n.to_hash(), notifications)
    return jsonify(notifications=list(n))

@app.route('/speakers')
def speakers_list():
    yaml_path = path.join(base_path, 'data', 'speakers', '*.yaml')
    speakers = map(lambda path: yaml.load(open(path).read()), glob(yaml_path))

    def f(speakers):
        for s in speakers:
            r = s['speaker']
            r['session'] = s['session']
            del(r['session']['speaker'])
            yield r
    return jsonify(speakers=list(f(speakers)))

def group_by_time(paths):
    data = list(map(lambda path: yaml.load(open(path).read()), paths))
    sessions = map(lambda x: x['session'], data)

    def start_at(session):
        return session['start_at']

    tires = itertools.groupby(sorted(sessions, key=start_at), key=start_at)
    for k, g in tires:
        yield {'start_at': k,
               'sessions': sorted(list(g), key=lambda s: s['room'])}

@app.route('/sessions')
def sessions_list():
    yaml_path = path.join(base_path, 'data', 'speakers', '*.yaml')
    match = glob(yaml_path)
    return jsonify(schedule=list(group_by_time(match)))

@app.route('/speakers/<entity>')
def get_entity(entity):
    match = glob(path.join(base_path, 'data', 'speakers', entity + '*.yaml'))
    for m in match:
        yaml_data = open(m).read()
        return jsonify(yaml.load(yaml_data))
    abort(404)

@app.route('/misc/<entity>')
def get_entity(entity):
    match = glob(path.join(base_path, 'data', 'misc', entity + '*.yaml'))
    for m in match:
        yaml_data = open(m).read()
        return jsonify(yaml.load(yaml_data))
    abort(404)

if __name__ == '__main__':
    app.run(debug=True)
<commit_msg>コピペが適当すぎた<commit_after># -*- coding: utf-8 -*-
from os import path, environ
from flask import Flask, jsonify, abort
import yaml
import json
from glob import glob
import itertools
import urbanairship as ua
import redis
import datetime
import time
import uuid
import sys

app = Flask(__name__)
base_path = path.dirname(path.abspath(__file__))

ua_app_key = environ['UA_APP_KEY']
ua_master_secret = environ['UA_MASTER_SECRET']
airship = ua.Airship(ua_app_key, ua_master_secret)

class DateTimeSupportJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime.datetime):
            return o.isoformat()
        return super(DateTimeSupportJSONEncoder, self).default(o)

class Session:
    def __init__(self, title, name, room, type=None):
        self.title = title
        self.name = name
        self.room = room

    def to_json(self):
        return json.dumps(self.to_hash())

    def to_hash(self):
        return {'title': self.title, 'name': self.name, 'room': self.room,
                'type': 'session'}

class Notification:
    def __init__(self, uuid, message, url, created_at, image):
        self.uuid = uuid
        self.message = message
        self.url = url
        self.image = image
        self.created_at = created_at

    def key(self):
        return 'notification.{}'.format(self.uuid)

    def to_json(self):
        return json.dumps(self.to_hash())

    def to_hash(self):
        return {'uuid': self.uuid, 'message': self.message,
                'url': self.url, 'created_at': self.created_at,
                'image': self.image}

    @classmethod
    def loads(cls, json_str):
        d = json.loads(json_str)
        return Notification(**d)

class NotificationStore:
    key = 'notifications'

    def __init__(self):
        self.r = redis.from_url(environ.get('REDIS_URL'))

    def add_notification(self, notification):
        self.r.zadd(self.key, notification.key(), notification.created_at)
        self.r.set(notification.key(), notification.to_json())

    def fetch_notifications(self):
        keys = self.r.zrange(self.key, 0, 100, desc=True)
        if len(keys) == 0:
            return []
        notifications = self.r.mget(keys)
        print(keys, file=sys.stderr)
        print(notifications, file=sys.stderr)
        return map(lambda n: Notification.loads(n.decode('utf-8')),
                   notifications)

    def remove_all(self):
        self.r.delete(self.key)

store = NotificationStore()

def send_notification(message):
    now = datetime.datetime.now()
    timestamp = int(time.mktime(now.timetuple()))
    store.add_notification(Notification(str(uuid.uuid4()), message,
                                        'hoge.com', timestamp,
                                        'http://image.com'))
    try:
        push = airship.create_push()
        push.audience = ua.all_
        notification = ua.ios(alert=message,
                              extra={'url': 'https://google.com'})
        push.ios = notification
        push.device_types = ua.ios
        push.send()
    except:
        return False
    return True

@app.route('/remove-all')
def remove_all():
    store.remove_all()
    return 'done'

@app.route('/apns')
def apns_send():
    message = 'Hello world2'
    send_notification(message)
    push = airship.create_push()
    push.audience = ua.all_
    push.notification = ua.notification(alert=message)
    push.device_types = ua.all_
    push.send()
    # try:
    # except:
    #     return 'error'
    return 'success'

@app.route('/notifications')
def notifications_list():
    notifications = store.fetch_notifications()
    n = map(lambda n: n.to_hash(), notifications)
    return jsonify(notifications=list(n))

@app.route('/speakers')
def speakers_list():
    yaml_path = path.join(base_path, 'data', 'speakers', '*.yaml')
    speakers = map(lambda path: yaml.load(open(path).read()), glob(yaml_path))

    def f(speakers):
        for s in speakers:
            r = s['speaker']
            r['session'] = s['session']
            del(r['session']['speaker'])
            yield r
    return jsonify(speakers=list(f(speakers)))

def group_by_time(paths):
    data = list(map(lambda path: yaml.load(open(path).read()), paths))
    sessions = map(lambda x: x['session'], data)

    def start_at(session):
        return session['start_at']

    tires = itertools.groupby(sorted(sessions, key=start_at), key=start_at)
    for k, g in tires:
        yield {'start_at': k,
               'sessions': sorted(list(g), key=lambda s: s['room'])}

@app.route('/sessions')
def sessions_list():
    yaml_path = path.join(base_path, 'data', 'speakers', '*.yaml')
    match = glob(yaml_path)
    return jsonify(schedule=list(group_by_time(match)))

@app.route('/speakers/<entity>')
def get_entity(entity):
    match = glob(path.join(base_path, 'data', 'speakers', entity + '*.yaml'))
    for m in match:
        yaml_data = open(m).read()
        return jsonify(yaml.load(yaml_data))
    abort(404)

@app.route('/misc/<entity>')
def get_misc(entity):
    match = glob(path.join(base_path, 'data', 'misc', entity + '*.yaml'))
    for m in match:
        yaml_data = open(m).read()
        return jsonify(yaml.load(yaml_data))
    abort(404)

if __name__ == '__main__':
    app.run(debug=True)
<|endoftext|>


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

###############################################################################
# Imports
###############################################################################

import errno
import select

from pants.shared import log

#: Detect which system calls are available.
_use_epoll, _use_kqueue = False, False
if hasattr(select, "epoll"):
    _use_epoll = True
elif hasattr(select, "kqueue"):
    _use_kqueue = True

###############################################################################
# Reactor Class
###############################################################################

class Reactor(object):
    """
    The reactor class.

    A reactor is an object that manages network channels and maintains
    consistent network activity on those channels' sockets.
    """
    #: Socket events - these correspond roughly to epoll() states.
    NONE = 0x00
    READ = 0x01
    WRITE = 0x04
    ERROR = 0x08 | 0x10 | 0x2000

    def __init__(self, poll=None):
        """
        Initialises the reactor.

        Parameters:
            poll - The polling object to be used by the reactor. This
                defaults to _EPoll on Linux 2.6+, _KQueue on BSD and
                _Select on all other operating systems.
        """
        if poll:
            self._poll = poll
        elif _use_epoll:
            self._poll = _EPoll()
        elif _use_kqueue:
            self._poll = _KQueue()
        else:
            self._poll = _Select()

        self._channels = {}
        self._events = {}

    ##### Channel Methods ###################################################

    def add_channel(self, channel):
        """
        Adds a channel to the reactor.

        Parameters:
            channel - A channel object.
        """
        self._channels[channel.fileno] = channel
        self._poll.add(channel.fileno, channel.events)

    def modify_channel(self, channel):
        """
        Modifies a channel's state.

        Parameters:
            channel - A channel object.
        """
        self._poll.modify(channel.fileno, channel.events)

    def remove_channel(self, channel):
        """
        Removes a channel from the reactor.

        Parameters:
            channel - A channel object.
        """
        self._channels.pop(channel.fileno, None)
        self._events.pop(channel.fileno, None)

        try:
            self._poll.remove(channel.fileno)
        except (IOError, OSError):
            log.exception("Error while removing channel %d." % channel.fileno)

    ##### Control Methods #####################################################

    def poll(self, timeout=0.02):
        """
        Polls the reactor.

        Identifies active sockets, then reads from, writes to and raises
        exceptions on those sockets.
        """
        try:
            events = self._poll.poll(timeout)
        except Exception, err: # TODO Is it Exception or select.error?
            if err[0] == errno.EINTR:
                log.warning("Interrupted system call.", exc_info=True)
                return
            else:
                raise

        self._events.update(events)

        for fileno, events in self._events.items():
            try:
                self._channels[fileno]._handle_events(events)
            except (IOError, OSError), err:
                if err[0] == errno.EPIPE:
                    # EPIPE: Broken pipe.
                    self._channels[fileno].close_immediately()
                else:
                    log.exception("Error while handling I/O events on channel %d." % fileno)
            except (KeyboardInterrupt, SystemExit):
                raise
            except Exception:
                log.exception("Error while handling I/O events on channel %d." % fileno)

###############################################################################
# _EPoll Class
###############################################################################

class _EPoll(object):
    """
    An epoll()-based polling object.
    """
    def __init__(self):
        """
        Initialises the _EPoll object.
        """
        self._epoll = select.epoll()
        self._events = {}

    def add(self, fileno, events):
        """
        Adds a socket to the polling object.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self._epoll.register(fileno, events)
        self._events[fileno] = events

    def modify(self, fileno, events):
        """
        Modifies a registered socket's state.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        if events == self._events[fileno]:
            # Save a tiny amount of time.
            return

        self._epoll.modify(fileno, events)

    def remove(self, fileno):
        """
        Removes a socket from the polling object.

        Parameters:
            fileno - The socket's file number.
        """
        self._epoll.unregister(fileno)
        self._events.pop(fileno, None)

    def poll(self, timeout):
        """
        Uses the epoll() system call to identify active sockets.

        epoll() can only be used on Linux 2.6+
        """
        epoll_events = self._epoll.poll(timeout)
        events = {}

        for fileno, event in epoll_events:
            if event & select.EPOLLIN:
                events[fileno] = events.get(fileno, 0) | Reactor.READ
            if event & select.EPOLLOUT:
                events[fileno] = events.get(fileno, 0) | Reactor.WRITE
            if event & (select.EPOLLERR | select.EPOLLHUP | 0x2000):
                events[fileno] = events.get(fileno, 0) | Reactor.ERROR

        return events

###############################################################################
# _KQueue Class
###############################################################################

class _KQueue(object):
    """
    A kqueue()-based polling object.
    """
    def __init__(self):
        """
        Initialises the _KQueue object.
        """
        self._kqueue = select.kqueue()
        self._events = {}

    def add(self, fileno, events):
        """
        Adds a socket to the polling object.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self._control(fileno, events, select.KQ_EV_ADD)
        self._events[fileno] = events

    def modify(self, fileno, events):
        """
        Modifies a registered socket's state.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self.remove(fileno)
        self.add(fileno, events)

    def remove(self, fileno):
        """
        Removes a socket from the polling object.

        Parameters:
            fileno - The socket's file number.
        """
        events = self._events.pop(fileno)
        self._control(fileno, events, select.KQ_EV_DELETE)

    def poll(self, timeout):
        """
        Uses the kqueue() system call to identify active sockets.

        kqueue() can only be used on BSD
        """
        kqueue_events = self._kqueue.control(None, 1024, timeout)
        events = {}

        for event in kqueue_events:
            fileno = event.ident

            if event.filter == select.KQ_FILTER_READ:
                events[fileno] = events.get(fileno, 0) | Reactor.READ
            if event.filter == select.KQ_FILTER_WRITE:
                events[fileno] = events.get(fileno, 0) | Reactor.WRITE
            if event.flags & select.KQ_EV_ERROR:
                events[fileno] = events.get(fileno, 0) | Reactor.ERROR

        return events

    def _control(self, fileno, events, flags):
        kqueue_events = []

        if events & Reactor.WRITE:
            event = select.kevent(fileno, filter=select.KQ_FILTER_WRITE,
                                  flags=flags)
            kqueue_events.append(event)

        if events & Reactor.READ or not kqueue_events:
            event = select.kevent(fileno, filter=select.KQ_FILTER_READ,
                                  flags=flags)
            kqueue_events.append(event)

        for event in kqueue_events:
            self._kqueue.control([event], 0)

###############################################################################
# _Select Class
###############################################################################

class _Select(object):
    """
    A select()-based polling object.
    """
    def __init__(self):
        """
        Initialises the _Select object.
        """
        self._r = set()
        self._w = set()
        self._e = set()

    def add(self, fileno, events):
        """
        Adds a socket to the polling object.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        if events & Reactor.READ:
            self._r.add(fileno)
        if events & Reactor.WRITE:
            self._w.add(fileno)
        if events & Reactor.ERROR:
            self._e.add(fileno)

    def modify(self, fileno, events):
        """
        Modifies a registered socket's state.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self.remove(fileno)
        self.add(fileno, events)

    def remove(self, fileno):
        """
        Removes a socket from the polling object.

        Parameters:
            fileno - The socket's file number.
        """
        self._r.discard(fileno)
        self._w.discard(fileno)
        self._e.discard(fileno)

    def poll(self, timeout):
        """
        Uses the select() system call to identify active sockets.

        select()'s performance is relatively poor. On Windows, it is
        limited to 512 file descriptors.
        """
        r, w, e, = select.select(self._r, self._w, self._e, timeout)

        events = {}

        for fileno in r:
            events[fileno] = events.get(fileno, 0) | Reactor.READ
        for fileno in w:
            events[fileno] = events.get(fileno, 0) | Reactor.WRITE
        for fileno in e:
            events[fileno] = events.get(fileno, 0) | Reactor.ERROR

        return events

###############################################################################
# Initialisation
###############################################################################

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

###############################################################################
# Imports
###############################################################################

import errno
import select

from pants.shared import log

#: Detect which system calls are available.
_use_epoll, _use_kqueue = False, False
if hasattr(select, "epoll"):
    _use_epoll = True
elif hasattr(select, "kqueue"):
    _use_kqueue = True

###############################################################################
# Reactor Class
###############################################################################

class Reactor(object):
    """
    The reactor class.

    A reactor is an object that manages network channels and maintains
    consistent network activity on those channels' sockets.
    """
    #: Socket events - these correspond to epoll() states.
    NONE = 0x00
    READ = 0x01
    WRITE = 0x04
    ERROR = 0x08 | 0x10 | 0x2000

    def __init__(self, poll=None):
        """
        Initialises the reactor.

        Parameters:
            poll - The polling object to be used by the reactor. This
                defaults to _EPoll on Linux 2.6+, _KQueue on BSD and
                _Select on all other operating systems.
        """
        if poll:
            self._poll = poll
        elif _use_epoll:
            self._poll = _EPoll()
        elif _use_kqueue:
            self._poll = _KQueue()
        else:
            self._poll = _Select()

        self._channels = {}

    ##### Channel Methods ###################################################

    def add_channel(self, channel):
        """
        Adds a channel to the reactor.

        Parameters:
            channel - A channel object.
        """
        self._channels[channel.fileno] = channel
        self._poll.add(channel.fileno, channel.events)

    def modify_channel(self, channel):
        """
        Modifies a channel's state.

        Parameters:
            channel - A channel object.
        """
        self._poll.modify(channel.fileno, channel.events)

    def remove_channel(self, channel):
        """
        Removes a channel from the reactor.

        Parameters:
            channel - A channel object.
        """
        self._channels.pop(channel.fileno, None)

        try:
            self._poll.remove(channel.fileno)
        except (IOError, OSError):
            log.exception("Error while removing channel %d." % channel.fileno)

    ##### Control Methods #####################################################

    def poll(self, timeout=0.02):
        """
        Polls the reactor.

        Identifies active sockets, then reads from, writes to and raises
        exceptions on those sockets.
        """
        try:
            events = self._poll.poll(timeout)
        except Exception, err: # TODO Is it Exception or select.error?
            if err[0] == errno.EINTR:
                log.warning("Interrupted system call.", exc_info=True)
                return
            else:
                raise

        for fileno, events in events.items():
            try:
                self._channels[fileno]._handle_events(events)
            except (IOError, OSError), err:
                if err[0] == errno.EPIPE:
                    # EPIPE: Broken pipe.
                    self._channels[fileno].close_immediately()
                else:
                    log.exception("Error while handling I/O events on channel %d." % fileno)
            except (KeyboardInterrupt, SystemExit):
                raise
            except Exception:
                log.exception("Error while handling I/O events on channel %d." % fileno)

###############################################################################
# _EPoll Class
###############################################################################

class _EPoll(object):
    """
    An epoll()-based polling object.
    """
    def __init__(self):
        """
        Initialises the _EPoll object.
        """
        self._epoll = select.epoll()

    def add(self, fileno, events):
        """
        Adds a socket to the polling object.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self._epoll.register(fileno, events)

    def modify(self, fileno, events):
        """
        Modifies a registered socket's state.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self._epoll.modify(fileno, events)

    def remove(self, fileno):
        """
        Removes a socket from the polling object.

        Parameters:
            fileno - The socket's file number.
        """
        self._epoll.unregister(fileno)

    def poll(self, timeout):
        """
        Uses the epoll() system call to identify active sockets.

        epoll() can only be used on Linux 2.6+
        """
        epoll_events = self._epoll.poll(timeout)
        events = {}

        for fileno, event in epoll_events:
            if event & select.EPOLLIN:
                events[fileno] = events.get(fileno, 0) | Reactor.READ
            if event & select.EPOLLOUT:
                events[fileno] = events.get(fileno, 0) | Reactor.WRITE
            if event & (select.EPOLLERR | select.EPOLLHUP | 0x2000):
                events[fileno] = events.get(fileno, 0) | Reactor.ERROR

        return events

###############################################################################
# _KQueue Class
###############################################################################

class _KQueue(object):
    """
    A kqueue()-based polling object.
    """
    def __init__(self):
        """
        Initialises the _KQueue object.
        """
        self._kqueue = select.kqueue()

    def add(self, fileno, events):
        """
        Adds a socket to the polling object.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self._control(fileno, events, select.KQ_EV_ADD)

    def modify(self, fileno, events):
        """
        Modifies a registered socket's state.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self.remove(fileno)
        self.add(fileno, events)

    def remove(self, fileno):
        """
        Removes a socket from the polling object.

        Parameters:
            fileno - The socket's file number.
        """
        self._control(fileno, events, select.KQ_EV_DELETE)

    def poll(self, timeout):
        """
        Uses the kqueue() system call to identify active sockets.

        kqueue() can only be used on BSD
        """
        kqueue_events = self._kqueue.control(None, 1024, timeout)
        events = {}

        for event in kqueue_events:
            fileno = event.ident

            if event.filter == select.KQ_FILTER_READ:
                events[fileno] = events.get(fileno, 0) | Reactor.READ
            if event.filter == select.KQ_FILTER_WRITE:
                events[fileno] = events.get(fileno, 0) | Reactor.WRITE
            if event.flags & select.KQ_EV_ERROR:
                events[fileno] = events.get(fileno, 0) | Reactor.ERROR

        return events

    def _control(self, fileno, events, flags):
        kqueue_events = []

        if events & Reactor.WRITE:
            event = select.kevent(fileno, filter=select.KQ_FILTER_WRITE,
                                  flags=flags)
            kqueue_events.append(event)

        if events & Reactor.READ or not kqueue_events:
            event = select.kevent(fileno, filter=select.KQ_FILTER_READ,
                                  flags=flags)
            kqueue_events.append(event)

        for event in kqueue_events:
            self._kqueue.control([event], 0)

###############################################################################
# _Select Class
###############################################################################

class _Select(object):
    """
    A select()-based polling object.
    """
    def __init__(self):
        """
        Initialises the _Select object.
        """
        self._r = set()
        self._w = set()
        self._e = set()

    def add(self, fileno, events):
        """
        Adds a socket to the polling object.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        if events & Reactor.READ:
            self._r.add(fileno)
        if events & Reactor.WRITE:
            self._w.add(fileno)
        if events & Reactor.ERROR:
            self._e.add(fileno)

    def modify(self, fileno, events):
        """
        Modifies a registered socket's state.

        Parameters:
            fileno - The socket's file number.
            events - The events the socket is listening for.
        """
        self.remove(fileno)
        self.add(fileno, events)

    def remove(self, fileno):
        """
        Removes a socket from the polling object.

        Parameters:
            fileno - The socket's file number.
        """
        self._r.discard(fileno)
        self._w.discard(fileno)
        self._e.discard(fileno)

    def poll(self, timeout):
        """
        Uses the select() system call to identify active sockets.

        select()'s performance is relatively poor. On Windows, it is
        limited to 512 file descriptors.
        """
        r, w, e, = select.select(self._r, self._w, self._e, timeout)

        events = {}

        for fileno in r:
            events[fileno] = events.get(fileno, 0) | Reactor.READ
        for fileno in w:
            events[fileno] = events.get(fileno, 0) | Reactor.WRITE
        for fileno in e:
            events[fileno] = events.get(fileno, 0) | Reactor.ERROR

        return events

###############################################################################
# Initialisation
###############################################################################

reactor = Reactor()
<|endoftext|>


<commit_before>#!/usr/bin/env python

import os
import stat
import sys
import getopt
import threading
from subprocess import call

thread = False
fork = True
src = None
dst = None
_dir = False
files = None
children = []

# PATHS
CP_PATH = "/bin/cp"
# END PATHS

def copy( _file ):
    _str = "%(path)s %(file)s %(dst)s" % { "path": CP_PATH, "file": _file, "dst": dst }
    call(_str, stdin=None, shell=True)

def copy_with_threads():
    if not _dir:
        current_thread = threading.currentThread()

        for _file in files:
            print _file, "\n"
            child_thread = threading.Thread(target=copy, name= _file, args=( _file, ))
            child_thread.start()

        for thread in threading.enumerate():
            if thread is current_thread:
                continue
            thread.join()

def copy_with_forks():
    global children
    os.setpgid(os.getpid(), os.getpid())
    if not _dir:
        for _file in files:
            if os.fork() == 0:
                children.append(os.getpid())
                copy( _file )

        for child in children:
            os.waitpid(child, 0)

def search_file( _file ):
    file_path = os.getcwd() + "/"+ _file
    if os.path.exists(file_path):
        return file_path
    elif os.path.exists(_file):
        return _file
    else:
        print _file, "Doesn't exist"
        raise Exception(_file + " Doesn't exist")

def verify_files():
    for _file in files:
        _file = search_file(_file)

def parse_options():
    global thread, fork, src, dst, files, _dir

    try:
        opts, args = getopt.getopt(sys.argv[1:], "h t f d", ["help", "with-threads", "with-forks", "dir", "src=", "dst="])

        for opt, arg in opts:
            if opt in ("-h", "--help"):
                pass
            elif opt in ("-d","--dir"):
                _dir = True
            elif opt == "--src":
                src = arg
            elif opt == "--dst":
                dst = arg
            elif opt in ("-t","--with-threads"):
                thread, fork = True, False
                pass
            elif opt in ("-f", "--with-forks"):
                thread, fork = False, True
                pass
            else:
                raise getopt.GetoptError("Unknown option\n")

        if len(args) == 0:
            raise Exception("No Files supplied\n")
        else:
            files = args
            verify_files()
    except getopt.GetoptError as err:
        print str(err)

if __name__ == '__main__':
    parse_options()
    if dst == None or len(dst) == 0:
        raise Exception("Destination must be supplied.\n")
    elif _dir == True and src == None:
        raise Exception("if -d or --dir flag is true source path must be supplied.\n")
    elif thread:
        copy_with_threads()
    elif forks:
        copy_with_forks()
<commit_msg>Parallel Copy using forks<commit_after>#!/usr/bin/env python

import os
import stat
import sys
import getopt
import threading
from signal import SIGKILL
from subprocess import call

thread = False
fork = True
src = None
dst = None
_dir = False
files = None
children = []

# PATHS
CP_PATH = "/bin/cp"
# END PATHS

def copy( _file ):
    _str = "%(path)s %(file)s %(dst)s" % { "path": CP_PATH, "file": _file, "dst": dst }
    call(_str, stdin=None, shell=True)

def copy_with_threads():
    if not _dir:
        current_thread = threading.currentThread()

        for _file in files:
            print _file, "\n"
            child_thread = threading.Thread(target=copy, name= _file, args=( _file, ))
            child_thread.start()

        for thread in threading.enumerate():
            if thread is current_thread:
                continue
            thread.join()

def copy_with_forks():
    global children
    parent_pid = os.getpid()
    os.setpgid(parent_pid,parent_pid)
    if not _dir:
        for _file in files:
            child_pid = os.fork()
            if child_pid:
                children.append(child_pid)
                copy( _file )
                break

        for child in children:
            os.waitpid(child, 0)

def search_file( _file ):
    file_path = os.getcwd() + "/"+ _file
    if os.path.exists(file_path):
        return file_path
    elif os.path.exists(_file):
        return _file
    else:
        print _file, "Doesn't exist"
        raise Exception(_file + " Doesn't exist")

def verify_files():
    for _file in files:
        _file = search_file(_file)

def parse_options():
    global thread, fork, src, dst, files, _dir

    try:
        opts, args = getopt.getopt(sys.argv[1:], "h t f d", ["help", "with-threads", "with-forks", "dir", "src=", "dst="])

        for opt, arg in opts:
            if opt in ("-h", "--help"):
                pass
            elif opt in ("-d","--dir"):
                _dir = True
            elif opt == "--src":
                src = arg
            elif opt == "--dst":
                dst = arg
            elif opt in ("-t","--with-threads"):
                thread, fork = True, False
                pass
            elif opt in ("-f", "--with-forks"):
                thread, fork = False, True
                pass
            else:
                raise getopt.GetoptError("Unknown option\n")

        if len(args) == 0:
            raise Exception("No Files supplied\n")
        else:
            files = args
            verify_files()
    except getopt.GetoptError as err:
        print str(err)

if __name__ == '__main__':
    parse_options()
    if dst == None or len(dst) == 0:
        raise Exception("Destination must be supplied.\n")
    elif _dir == True and src == None:
        raise Exception("if -d or --dir flag is true source path must be supplied.\n")
    elif thread:
        copy_with_threads()
    elif fork:
        copy_with_forks()
<|endoftext|>


<commit_before>"""
A simple approach to versioning that replaces the need to manually
maintain __version__ strings without requiring larger, less elegant
solutions (e.g. versioneer.py).

It is easy to forget to update __version__ strings when releasing a
project and it is important that the __version__ strings are useful
over the course of development, especially if releases are infrequent.

The Version class is designed to solve these problems, acting as a
simple version string for released versions while making additional
information accessible when working with version control during
development (currently only supports git). Here is a typical example
of how it is used:

__version__ = param.Version(release=(1,0), fpath=__file__)

The Version class assumes that you will tag the release in your
version control system with a string in the form v*.* before the
release is made. By calling the Version.verify method from setup.py,
you will be reminded to create this tag (is it has been forgotten) and
will check that all versioning information has been properly updated.
"""

__author__ = 'Jean-Luc Stevens'

import os, subprocess

class Version(object):
    """
    A simple, approach to versioning that supports PyPI releases and
    additional information when working with git version control. When
    obtaining from PyPI, the version is the supplied release tuple.

    During development `git describe` will be used to compute the
    number of commits since the last version tag, the short commit
    hash and determine if the commit is dirty. Version tags must start
    with a lowercase 'v' e.g. v1.0, v2.0, v0.9.8 etc.

    Note that when git is used, the comparison operators take into
    account the number of commits since the last version tag. This
    approach is often useful in practice but may fail when using
    distributed version control across forks and branches.

    To add git archive support in your project's '__init__.py' file
    you will need to set the following line in .gitattributes:

    __init__.py export-subst
    """

    def __init__(self, release=None, fpath=None, commit=None):
        """
        release:  Release tuple (corresponding to the current git tag)
        fpath:    Set to __file__ to access version control information
        describe: Set to "$Format:%h$" (double quotes) for git archive
        """
        self.fpath = fpath
        self._expected_commit = commit
        self.expected_release = release

        self._commit = None if commit in [None, "$Format:%h$"] else commit
        self._commit_count = 0
        self._release = None
        self._dirty = False

    @property
    def release(self):
        "Return the release tuple"
        return self.fetch()._release

    @property
    def commit(self):
        "The short git SHA"
        return self.fetch()._commit

    @property
    def commit_count(self):
        "Return the number of commits since the last release"
        return self.fetch()._commit_count

    @property
    def dirty(self):
        "True if there are uncommited changes, False otherwise"
        return self.fetch()._dirty

    def fetch(self):
        """
        Returns a tuple of the major version together with the
        appropriate SHA and dirty bit (for development version only).
        """
        if self._release is not None:
            return self

        self._release = self.expected_release
        if not self.fpath:
            self._commit = self._expected_commit
            return self

         # Only git right now but easily extended to SVN, Mercurial etc.
        for cmd in ['git', 'git.cmd', 'git.exe']:
            try:
                self.git_fetch(cmd)
                break
            except EnvironmentError:
                pass
        return self

    def git_fetch(self, cmd='git'):
        cmd = [cmd, 'describe', '--long', '--match', 'v*.*', '--dirty']
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                cwd=os.path.dirname(self.fpath))
        output, error = (str(s.decode()).strip() for s in proc.communicate())

        if error=='fatal: No names found, cannot describe anything.':
            raise Exception("Cannot find any git version tags of format v*.*")

        # If there is any other error, return (release value still useful)
        if proc.returncode != 0: return self

        split = output[1:].split('-')
        self._release = tuple(int(el) for el in split[0].split('.'))
        self._commit_count = int(split[1])
        self._commit = str(split[2][1:]) # Strip out 'g' prefix ('g'=>'git')
        self._dirty = (split[-1]=='dirty')
        return self

    def __str__(self):
        """
        Version in in x.y.z string format. Does not include the 'v'
        prefix of git version tags as format does not appear to be pip
        compatible.
        """
        return '.'.join(str(el) for el in self.release)

    def __repr__(self):
        return "Version(%r,%r,%r)" % (self.release,
                                      self.fpath if self.fpath else None,
                                      self.commit)

    def __eq__(self, other):
        if self.dirty or other.dirty: return False
        return (self.release, self.commit_count) == (other.release, other.commit_count)

    def __gt__(self, other):
        return (self.release, self.commit_count) > (other.release, other.commit_count)

    def __lt__(self, other):
        return (self.release, self.commit_count) < (other.release, other.commit_count)

    def verify(self):
        """
        Check the version information is consistent with git before
        doing a release. Should be called from setup.py when releasing
        to PyPI.
        """
        if self.release != self.expected_release:
            raise Exception("Declared release does not match current release tag.")

        if self.commit_count !=0:
            raise Exception("Please update the git version tag before release.")

        if self._expected_commit not in [None, "$Format:%h$"]:
            raise Exception("Declared release does not match git version tag")
<commit_msg>The version string follows git describe format unless clean release<commit_after>"""
A simple approach to versioning that replaces the need to manually
maintain __version__ strings without requiring larger, less elegant
solutions (e.g. versioneer.py).

It is easy to forget to update __version__ strings when releasing a
project and it is important that the __version__ strings are useful
over the course of development, especially if releases are infrequent.

The Version class is designed to solve these problems, acting as a
simple version string for released versions while making additional
information accessible when working with version control during
development (currently only supports git). Here is a typical example
of how it is used:

__version__ = param.Version(release=(1,0), fpath=__file__)

The Version class assumes that you will tag the release in your
version control system with a string in the form v*.* before the
release is made. By calling the Version.verify method from setup.py,
you will be reminded to create this tag (is it has been forgotten) and
will check that all versioning information has been properly updated.
"""

__author__ = 'Jean-Luc Stevens'

import os, subprocess

class Version(object):
    """
    A simple, approach to versioning that supports PyPI releases and
    additional information when working with git version control. When
    obtaining from PyPI, the version is the supplied release tuple.

    During development `git describe` will be used to compute the
    number of commits since the last version tag, the short commit
    hash and determine if the commit is dirty. Version tags must start
    with a lowercase 'v' e.g. v1.0, v2.0, v0.9.8 etc.

    Note that when git is used, the comparison operators take into
    account the number of commits since the last version tag. This
    approach is often useful in practice but may fail when using
    distributed version control across forks and branches.

    To add git archive support in your project's '__init__.py' file
    you will need to set the following line in .gitattributes:

    __init__.py export-subst
    """

    def __init__(self, release=None, fpath=None, commit=None):
        """
        release:  Release tuple (corresponding to the current git tag)
        fpath:    Set to __file__ to access version control information
        describe: Set to "$Format:%h$" (double quotes) for git archive
        """
        self.fpath = fpath
        self._expected_commit = commit
        self.expected_release = release

        self._commit = None if commit in [None, "$Format:%h$"] else commit
        self._commit_count = 0
        self._release = None
        self._dirty = False

    @property
    def release(self):
        "Return the release tuple"
        return self.fetch()._release

    @property
    def commit(self):
        "The short git SHA"
        return self.fetch()._commit

    @property
    def commit_count(self):
        "Return the number of commits since the last release"
        return self.fetch()._commit_count

    @property
    def dirty(self):
        "True if there are uncommited changes, False otherwise"
        return self.fetch()._dirty

    def fetch(self):
        """
        Returns a tuple of the major version together with the
        appropriate SHA and dirty bit (for development version only).
        """
        if self._release is not None:
            return self

        self._release = self.expected_release
        if not self.fpath:
            self._commit = self._expected_commit
            return self

         # Only git right now but easily extended to SVN, Mercurial etc.
        for cmd in ['git', 'git.cmd', 'git.exe']:
            try:
                self.git_fetch(cmd)
                break
            except EnvironmentError:
                pass
        return self

    def git_fetch(self, cmd='git'):
        cmd = [cmd, 'describe', '--long', '--match', 'v*.*', '--dirty']
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                cwd=os.path.dirname(self.fpath))
        output, error = (str(s.decode()).strip() for s in proc.communicate())

        if error=='fatal: No names found, cannot describe anything.':
            raise Exception("Cannot find any git version tags of format v*.*")

        # If there is any other error, return (release value still useful)
        if proc.returncode != 0: return self

        split = output[1:].split('-')
        self._release = tuple(int(el) for el in split[0].split('.'))
        self._commit_count = int(split[1])
        self._commit = str(split[2][1:]) # Strip out 'g' prefix ('g'=>'git')
        self._dirty = (split[-1]=='dirty')
        return self

    def __str__(self):
        """
        Version in in x.y.z string format. Does not include the 'v'
        prefix of git version tags as format does not appear to be pip
        compatible.

        If the commit count is non-zero or the repository is dirty the
        string representation is equivalent to output of:

        `git describe --long --match v*.* --dirty` ('v' prefix removed)
        """
        release = '.'.join(str(el) for el in self.release)
        if self.commit_count == 0 and not self.dirty:
            return release

        dirty_status = '-dirty' if self.dirty else ''
        return '%s-%d-g%s%s' % (release, self.commit_count,
                                self.commit, dirty_status)

    def __repr__(self):
        return "Version(%r,%r,%r)" % (self.release,
                                      self.fpath if self.fpath else None,
                                      self.commit)

    def __eq__(self, other):
        if self.dirty or other.dirty: return False
        return (self.release, self.commit_count) == (other.release, other.commit_count)

    def __gt__(self, other):
        return (self.release, self.commit_count) > (other.release, other.commit_count)

    def __lt__(self, other):
        return (self.release, self.commit_count) < (other.release, other.commit_count)

    def verify(self):
        """
        Check the version information is consistent with git before
        doing a release. Should be called from setup.py when releasing
        to PyPI.
        """
        if self.release != self.expected_release:
            raise Exception("Declared release does not match current release tag.")

        if self.commit_count !=0:
            raise Exception("Please update the git version tag before release.")

        if self._expected_commit not in [None, "$Format:%h$"]:
            raise Exception("Declared release does not match git version tag")
<|endoftext|>