<commit_before>#
# Jasy - Web Tooling Framework
# Copyright 2010-2012 Zynga Inc.
#

import re, json, os, fnmatch

import jasy.core.File
import jasy.item.Asset
import jasy.core.Json as Json

from jasy import UserError
import jasy.core.Console as Console

__all__ = ["AssetManager"]

class AssetManager:
    """
    Manages assets aka images, styles and other files required for a web application.

    Supports filtering assets based on a given class list (with optional permutation) to
    only include and copy assets which are needed by the current implementation. This is
    especially useful when only parts of dependend projects are actually used.

    Merges assets with the same name from different projects. But normally each project
    creates it's own sandbox namespace so this has not often any effect at all.

    Supports images and automatically detect their size and image format. Both informations
    are added to the exported data later on.
    """

    def __init__(self, session):

        Console.info("Initializing assets...")
        Console.indent()

        # Store session reference (one asset manager per session)
        self.__session = session

        # Stores manager contextual asset information (like relative paths)
        self.__data = {}

        # Registry for profiles aka asset groups
        self.__profiles = []

        # Loop though all projects and merge assets
        assets = self.__assets = {}
        for project in self.__session.getProjects():
            assets.update(project.getAssets())

        self.__processSprites()
        self.__processAnimations()

        Console.outdent()
        Console.info("Activated %s assets", len(assets))

    def __processSprites(self):
        """Processes jasysprite.json files to merge sprite data into asset registry"""

        assets = self.__assets
        configs = [fileId for fileId in assets if assets[fileId].isImageSpriteConfig()]

        if configs:
            Console.info("Processing %s image sprite configs...", len(configs))

        sprites = []
        Console.indent()
        for fileId in configs:
            Console.debug("Processing %s...", fileId)

            asset = assets[fileId]
            spriteBase = os.path.dirname(fileId)

            try:
                spriteConfig = asset.getParsedObject();
            except ValueError as err:
                raise UserError("Could not parse jasysprite.json at %s: %s" % (fileId, err))

            Console.indent()
            for spriteImage in spriteConfig:
                spriteImageId = "%s/%s" % (spriteBase, spriteImage)

                singleRelPaths = spriteConfig[spriteImage]
                Console.debug("Image %s combines %s images", spriteImageId, len(singleRelPaths))

                for singleRelPath in singleRelPaths:
                    singleId = "%s/%s" % (spriteBase, singleRelPath)
                    singleData = singleRelPaths[singleRelPath]

                    if singleId in assets:
                        singleAsset = assets[singleId]
                    else:
                        Console.info("Creating new asset: %s", singleId)
                        singleAsset = jasy.item.Asset.AssetItem(None)
                        assets[singleId] = singleAsset

                    if not spriteImageId in sprites:
                        spriteImageIndex = len(sprites)
                        sprites.append(spriteImageId)
                    else:
                        spriteImageIndex = sprites.index(spriteImageId)

                    singleAsset.addImageSpriteData(spriteImageIndex, singleData["left"], singleData["top"])

                    if "width" in singleData and "height" in singleData:
                        singleAsset.addImageDimensionData(singleData["width"], singleData["height"])

                    # Verify that sprite sheet is up-to-date
                    if "checksum" in singleData:
                        fileChecksum = singleAsset.getChecksum()
                        storedChecksum = singleData["checksum"]

                        Console.debug("Checksum Compare: %s <=> %s", fileChecksum[0:6], storedChecksum[0:6])

                        if storedChecksum != fileChecksum:
                            raise UserError("Sprite Sheet is not up-to-date. Checksum of %s differs.", singleId)

            Console.outdent()
            Console.debug("Deleting sprite config from assets: %s", fileId)
            del assets[fileId]

        Console.outdent()
        self.__sprites = sprites

    def __processAnimations(self):
        """Processes jasyanimation.json files to merge animation data into asset registry"""

        assets = self.__assets
        configs = [fileId for fileId in assets if assets[fileId].isImageAnimationConfig()]

        if configs:
            Console.info("Processing %s image animation configs...", len(configs))

        Console.indent()
        for fileId in configs:
            Console.debug("Processing %s...", fileId)

            asset = assets[fileId]
            base = os.path.dirname(fileId)

            try:
                config = json.loads(asset.getText())
            except ValueError as err:
                raise UserError("Could not parse jasyanimation.json at %s: %s" % (fileId, err))

            for relPath in config:
                imageId = "%s/%s" % (base, relPath)
                data = config[relPath]

                if not imageId in assets:
                    raise UserError("Unknown asset %s in %s" % (imageId, fileId))

                animationAsset = assets[imageId]

                if "rows" in data or "columns" in data:
                    rows = Util.getKey(data, "rows", 1)
                    columns = Util.getKey(data, "columns", 1)
                    frames = Util.getKey(data, "frames")

                    animationAsset.addImageAnimationData(columns, rows, frames)

                    if frames is None:
                        frames = rows * columns

                elif "layout" in data:
                    layout = data["layout"]
                    animationAsset.addImageAnimationData(None, None, layout=layout)
                    frames = len(layout)

                else:
                    raise UserError("Invalid image frame data for: %s" % imageId)

                Console.debug("  - Animation %s has %s frames", imageId, frames)

            Console.debug("  - Deleting animation config from assets: %s", fileId)
            del assets[fileId]

        Console.outdent()

    def addProfile(self, name, root=None, config=None, items=None):
        """
        Adds a new profile to the manager. This is basically the plain
        version of addSourceProfile/addBuildProfile which gives complete
        manual control of where to load the assets from. This is useful
        for e.g. supporting a complete custom loading scheme aka complex
        CDN based setup.
        """

        profiles = self.__profiles
        for entry in profiles:
            if entry["name"] == name:
                raise UserError("Asset profile %s was already defined!" % name)

        profile = {
            "name" : name
        }

        if root:
            if not root.endswith("/"):
                root += "/"

            profile["root"] = root

        if config is not None:
            profile.update(config)

        unique = len(profiles)
        profiles.append(profile)

        if items:
            for fileId in items:
                items[fileId]["p"] = unique

            self.__addRuntimeData(items)

        return unique

    def addSourceProfile(self, urlPrefix="", override=False):
        """
        Adds a profile to include assets as being available in source tasks.

        This basically means that assets from all projects are referenced via
        relative URLs to the main project.

        Note 1: This automatically updates all currently known assets to
        reference the build profile.

        Note 2: This method only adds profile data to any assets when either
        there is no profile registered yet or override is set to True.
        """

        # First create a new profile with optional (CDN-) URL prefix
        profileId = self.addProfile("source", urlPrefix)

        # Then export all relative paths to main project and add this to the runtime data
        main = self.__session.getMain()
        assets = self.__assets
        data = self.__data

        for fileId in assets:
            if not fileId in data:
                data[fileId] = {}

            if override or not "p" in data[fileId]:
                data[fileId]["p"] = profileId
                data[fileId]["u"] = main.toRelativeUrl(assets[fileId].getPath())

        return self

    def addBuildProfile(self, urlPrefix="asset", override=False):
        """
        Adds a profile to include assets as being available in build tasks.

        This basically means that assets from all projects are copied to
        a local directory inside the build folder.

        Note 1: This automatically updates all currently known assets to
        reference the build profile.

        Note 2: This method only adds profile data to any assets when either
        there is no profile registered yet or override is set to True.
        """

        # First create a new profile with optional (CDN-) URL prefix
        profileId = self.addProfile("build", urlPrefix)

        # Then export all relative paths to main project and add this to the runtime data
        main = self.__session.getMain()
        assets = self.__assets
        data = self.__data

        for fileId in assets:
            if not fileId in data:
                data[fileId] = {}

            if override or not "p" in data[fileId]:
                data[fileId]["p"] = profileId

        return self

    def __addRuntimeData(self, runtime):
        assets = self.__assets
        data = self.__data

        for fileId in runtime:
            if not fileId in assets:
                Console.debug("Unknown asset: %s" % fileId)
                continue

            if not fileId in data:
                data[fileId] = {}

            data[fileId].update(runtime[fileId])

        return self

    def __structurize(self, data):
        """
        This method structurizes the incoming data into a cascaded structure representing the
        file system location (aka file IDs) as a tree. It further extracts the extensions and
        merges files with the same name (but different extensions) into the same entry. This is
        especially useful for alternative formats like audio files, videos and fonts. It only
        respects the data of the first entry! So it is not a good idea to have different files
        with different content stored with the same name e.g. content.css and content.png.
        """

        root = {}

        # Easier to debug and understand when sorted
        for fileId in sorted(data):
            current = root
            splits = fileId.split("/")

            # Extract the last item aka the filename itself
            basename = splits.pop()

            # Find the current node to store info on
            for split in splits:
                if not split in current:
                    current[split] = {}
                elif type(current[split]) != dict:
                    raise UserError("Invalid asset structure. Folder names must not be identical to any filename without extension: \"%s\" in %s" % (split, fileId))

                current = current[split]

            # Create entry
            Console.debug("Adding %s..." % fileId)
            current[basename] = data[fileId]

        return root

    def __compileFilterExpr(self, classes):
        """Returns the regular expression object to use for filtering"""

        # Merge asset hints from all classes and remove duplicates
        hints = set()
        for classObj in classes:
            hints.update(classObj.getMetaData(self.__session.getCurrentPermutation()).assets)

        # Compile filter expressions
        matcher = "^%s$" % "|".join(["(%s)" % fnmatch.translate(hint) for hint in hints])
        Console.debug("Compiled asset matcher: %s" % matcher)

        return re.compile(matcher)

    def deploy(self, classes, assetFolder="$prefix/asset"):
        """
        Deploys all asset files to the destination asset folder. This merges
        assets from different projects into one destination folder.
        """

        assets = self.__assets
        projects = self.__session.getProjects()

        copyAssetFolder = self.__session.expandFileName(assetFolder)
        filterExpr = self.__compileFilterExpr(classes)

        Console.info("Deploying assets...")

        counter = 0
        length = len(assets)

        for fileId in assets:
            if not filterExpr.match(fileId):
                length -= 1
                continue

            srcFile = assets[fileId].getPath()
            dstFile = os.path.join(copyAssetFolder, fileId.replace("/", os.sep))

            if jasy.core.File.syncfile(srcFile, dstFile):
                counter += 1

        Console.info("Updated %s/%s files" % (counter, length))

    def export(self, classes=None, compress=True):
        """
        Exports asset data for usage at the client side. Utilizes JavaScript
        class jasy.Asset to inject data into the client at runtime.
        """

        # Processing assets
        assets = self.__assets
        data = self.__data

        result = {}
        filterExpr = self.__compileFilterExpr(classes) if classes else None
        for fileId in assets:
            if filterExpr and not filterExpr.match(fileId):
                continue

            entry = {}

            asset = assets[fileId]
            entry["t"] = asset.getType(short=True)

            assetData = asset.exportData()
            if assetData:
                entry["d"] = assetData

            if fileId in data:
                entry.update(data[fileId])

            result[fileId] = entry

        # Ignore empty result
        if not result:
            return None

        Console.info("Exported %s assets", len(result))

        return "jasy.Asset.addData(%s);" % Json.toJson({
            "assets" : self.__structurize(result),
            "profiles" : self.__profiles,
            "sprites" : self.__sprites
        }, compress=compress)

<commit_msg>Minor fix<commit_after>#
# Jasy - Web Tooling Framework
# Copyright 2010-2012 Zynga Inc.
#

import re, json, os, fnmatch

import jasy.core.File
import jasy.item.Asset
import jasy.core.Json as Json

from jasy import UserError
import jasy.core.Console as Console

__all__ = ["AssetManager"]

class AssetManager:
    """
    Manages assets aka images, styles and other files required for a web application.

    Supports filtering assets based on a given class list (with optional permutation) to
    only include and copy assets which are needed by the current implementation. This is
    especially useful when only parts of dependend projects are actually used.

    Merges assets with the same name from different projects. But normally each project
    creates it's own sandbox namespace so this has not often any effect at all.

    Supports images and automatically detect their size and image format. Both informations
    are added to the exported data later on.
    """

    def __init__(self, session):

        Console.info("Initializing assets...")
        Console.indent()

        # Store session reference (one asset manager per session)
        self.__session = session

        # Stores manager contextual asset information (like relative paths)
        self.__data = {}

        # Registry for profiles aka asset groups
        self.__profiles = []

        # Loop though all projects and merge assets
        assets = self.__assets = {}
        for project in self.__session.getProjects():
            assets.update(project.getAssets())

        self.__processSprites()
        self.__processAnimations()

        Console.outdent()
        Console.info("Activated %s assets", len(assets))

    def __processSprites(self):
        """Processes jasysprite.json files to merge sprite data into asset registry"""

        assets = self.__assets
        configs = [fileId for fileId in assets if assets[fileId].isImageSpriteConfig()]

        if configs:
            Console.info("Processing %s image sprite configs...", len(configs))

        sprites = []
        Console.indent()
        for fileId in configs:
            Console.debug("Processing %s...", fileId)

            asset = assets[fileId]
            spriteBase = os.path.dirname(fileId)

            try:
                spriteConfig = asset.getParsedObject();
            except ValueError as err:
                raise UserError("Could not parse jasysprite.json at %s: %s" % (fileId, err))

            Console.indent()
            for spriteImage in spriteConfig:
                spriteImageId = "%s/%s" % (spriteBase, spriteImage)

                singleRelPaths = spriteConfig[spriteImage]
                Console.debug("Image %s combines %s images", spriteImageId, len(singleRelPaths))

                for singleRelPath in singleRelPaths:
                    singleId = "%s/%s" % (spriteBase, singleRelPath)
                    singleData = singleRelPaths[singleRelPath]

                    if singleId in assets:
                        singleAsset = assets[singleId]
                    else:
                        Console.info("Creating new asset: %s", singleId)
                        singleAsset = jasy.item.Asset.AssetItem(None)
                        assets[singleId] = singleAsset

                    if not spriteImageId in sprites:
                        spriteImageIndex = len(sprites)
                        sprites.append(spriteImageId)
                    else:
                        spriteImageIndex = sprites.index(spriteImageId)

                    singleAsset.addImageSpriteData(spriteImageIndex, singleData["left"], singleData["top"])

                    if "width" in singleData and "height" in singleData:
                        singleAsset.addImageDimensionData(singleData["width"], singleData["height"])

                    # Verify that sprite sheet is up-to-date
                    if "checksum" in singleData:
                        fileChecksum = singleAsset.getChecksum()
                        storedChecksum = singleData["checksum"]

                        Console.debug("Checksum Compare: %s <=> %s", fileChecksum[0:6], storedChecksum[0:6])

                        if storedChecksum != fileChecksum:
                            raise UserError("Sprite Sheet is not up-to-date. Checksum of %s differs.", singleId)

            Console.outdent()
            Console.debug("Deleting sprite config from assets: %s", fileId)
            del assets[fileId]

        Console.outdent()
        self.__sprites = sprites

    def __processAnimations(self):
        """Processes jasyanimation.json files to merge animation data into asset registry"""

        assets = self.__assets
        configs = [fileId for fileId in assets if assets[fileId].isImageAnimationConfig()]

        if configs:
            Console.info("Processing %s image animation configs...", len(configs))

        Console.indent()
        for fileId in configs:
            Console.debug("Processing %s...", fileId)

            asset = assets[fileId]
            base = os.path.dirname(fileId)

            try:
                config = json.loads(asset.getText())
            except ValueError as err:
                raise UserError("Could not parse jasyanimation.json at %s: %s" % (fileId, err))

            for relPath in config:
                imageId = "%s/%s" % (base, relPath)
                data = config[relPath]

                if not imageId in assets:
                    raise UserError("Unknown asset %s in %s" % (imageId, fileId))

                animationAsset = assets[imageId]

                if "rows" in data or "columns" in data:
                    rows = Util.getKey(data, "rows", 1)
                    columns = Util.getKey(data, "columns", 1)
                    frames = Util.getKey(data, "frames")

                    animationAsset.addImageAnimationData(columns, rows, frames)

                    if frames is None:
                        frames = rows * columns

                elif "layout" in data:
                    layout = data["layout"]
                    animationAsset.addImageAnimationData(None, None, layout=layout)
                    frames = len(layout)

                else:
                    raise UserError("Invalid image frame data for: %s" % imageId)

                Console.debug("  - Animation %s has %s frames", imageId, frames)

            Console.debug("  - Deleting animation config from assets: %s", fileId)
            del assets[fileId]

        Console.outdent()

    def addProfile(self, name, root=None, config=None, items=None):
        """
        Adds a new profile to the manager. This is basically the plain
        version of addSourceProfile/addBuildProfile which gives complete
        manual control of where to load the assets from. This is useful
        for e.g. supporting a complete custom loading scheme aka complex
        CDN based setup.
        """

        profiles = self.__profiles
        for entry in profiles:
            if entry["name"] == name:
                raise UserError("Asset profile %s was already defined!" % name)

        profile = {
            "name" : name
        }

        if root:
            if not root.endswith("/"):
                root += "/"

            profile["root"] = root

        if config is not None:
            profile.update(config)

        unique = len(profiles)
        profiles.append(profile)

        if items:
            for fileId in items:
                items[fileId]["p"] = unique

            self.__addRuntimeData(items)

        return unique

    def addSourceProfile(self, urlPrefix="", override=False):
        """
        Adds a profile to include assets as being available in source tasks.

        This basically means that assets from all projects are referenced via
        relative URLs to the main project.

        Note 1: This automatically updates all currently known assets to
        reference the build profile.

        Note 2: This method only adds profile data to any assets when either
        there is no profile registered yet or override is set to True.
        """

        # First create a new profile with optional (CDN-) URL prefix
        profileId = self.addProfile("source", urlPrefix)

        # Then export all relative paths to main project and add this to the runtime data
        main = self.__session.getMain()
        assets = self.__assets
        data = self.__data

        for fileId in assets:
            if not fileId in data:
                data[fileId] = {}

            if override or not "p" in data[fileId]:
                data[fileId]["p"] = profileId
                data[fileId]["u"] = main.toRelativeUrl(assets[fileId].getPath())

        return self

    def addBuildProfile(self, urlPrefix="asset", override=False):
        """
        Adds a profile to include assets as being available in build tasks.

        This basically means that assets from all projects are copied to
        a local directory inside the build folder.

        Note 1: This automatically updates all currently known assets to
        reference the build profile.

        Note 2: This method only adds profile data to any assets when either
        there is no profile registered yet or override is set to True.
        """

        # First create a new profile with optional (CDN-) URL prefix
        profileId = self.addProfile("build", urlPrefix)

        # Then export all relative paths to main project and add this to the runtime data
        main = self.__session.getMain()
        assets = self.__assets
        data = self.__data

        for fileId in assets:
            if not fileId in data:
                data[fileId] = {}

            if override or not "p" in data[fileId]:
                data[fileId]["p"] = profileId

        return self

    def __addRuntimeData(self, runtime):
        assets = self.__assets
        data = self.__data

        for fileId in runtime:
            if not fileId in assets:
                Console.debug("Unknown asset: %s" % fileId)
                continue

            if not fileId in data:
                data[fileId] = {}

            data[fileId].update(runtime[fileId])

        return self

    def __structurize(self, data):
        """
        This method structurizes the incoming data into a cascaded structure representing the
        file system location (aka file IDs) as a tree. It further extracts the extensions and
        merges files with the same name (but different extensions) into the same entry. This is
        especially useful for alternative formats like audio files, videos and fonts. It only
        respects the data of the first entry! So it is not a good idea to have different files
        with different content stored with the same name e.g. content.css and content.png.
        """

        root = {}

        # Easier to debug and understand when sorted
        for fileId in sorted(data):
            current = root
            splits = fileId.split("/")

            # Extract the last item aka the filename itself
            basename = splits.pop()

            # Find the current node to store info on
            for split in splits:
                if not split in current:
                    current[split] = {}
                elif type(current[split]) != dict:
                    raise UserError("Invalid asset structure. Folder names must not be identical to any filename without extension: \"%s\" in %s" % (split, fileId))

                current = current[split]

            # Create entry
            Console.debug("Adding %s..." % fileId)
            current[basename] = data[fileId]

        return root

    def __compileFilterExpr(self, classes):
        """Returns the regular expression object to use for filtering"""

        # Merge asset hints from all classes and remove duplicates
        hints = set()
        for classObj in classes:
            hints.update(classObj.getMetaData(self.__session.getCurrentPermutation()).assets)

        # Compile filter expressions
        matcher = "^%s$" % "|".join(["(%s)" % fnmatch.translate(hint) for hint in hints])
        Console.debug("Compiled asset matcher: %s" % matcher)

        return re.compile(matcher)

    def deploy(self, classes, assetFolder=None):
        """
        Deploys all asset files to the destination asset folder. This merges
        assets from different projects into one destination folder.
        """

        # Sometimes it's called with explicit None - we want to fill the default
        # in that case as well.
        if assetFolder is None:
            assetFolder = "$prefix/asset"

        assets = self.__assets
        projects = self.__session.getProjects()

        copyAssetFolder = self.__session.expandFileName(assetFolder)
        filterExpr = self.__compileFilterExpr(classes)

        Console.info("Deploying assets...")

        counter = 0
        length = len(assets)

        for fileId in assets:
            if not filterExpr.match(fileId):
                length -= 1
                continue

            srcFile = assets[fileId].getPath()
            dstFile = os.path.join(copyAssetFolder, fileId.replace("/", os.sep))

            if jasy.core.File.syncfile(srcFile, dstFile):
                counter += 1

        Console.info("Updated %s/%s files" % (counter, length))

    def export(self, classes=None, compress=True):
        """
        Exports asset data for usage at the client side. Utilizes JavaScript
        class jasy.Asset to inject data into the client at runtime.
        """

        # Processing assets
        assets = self.__assets
        data = self.__data

        result = {}
        filterExpr = self.__compileFilterExpr(classes) if classes else None
        for fileId in assets:
            if filterExpr and not filterExpr.match(fileId):
                continue

            entry = {}

            asset = assets[fileId]
            entry["t"] = asset.getType(short=True)

            assetData = asset.exportData()
            if assetData:
                entry["d"] = assetData

            if fileId in data:
                entry.update(data[fileId])

            result[fileId] = entry

        # Ignore empty result
        if not result:
            return None

        Console.info("Exported %s assets", len(result))

        return "jasy.Asset.addData(%s);" % Json.toJson({
            "assets" : self.__structurize(result),
            "profiles" : self.__profiles,
            "sprites" : self.__sprites
        }, compress=compress)

<|endoftext|>


<commit_before>import stp
from rj_gameplay.role import dumb_move
from typing import List, Tuple

from rj_msgs.msg import RobotIntent

class LineTactic(stp.tactic.Tactic):
    # TODO docs

    def __init__(self, world_state: stp.rc.WorldState):
        super().__init__(world_state)

        # compute move points
        start = (3.0, 0.0)
        dy = 0.5
        self.move_points = [(start[0], start[1] + i * dy) for i in range(6)]

        # request closest robot every pt
        for pt in self.move_points:
            # for some reason stp.role doesn't need to be imported?
            self._role_requests.append(
                (stp.role.cost.PickClosestRobot(pt), dumb_move.DumbMove)
            )

        # OR hardcode certain ids to go
        # for i, pt in enumerate(self.move_points):
        #     self._role_requests.append((stp.role.cost.PickRobotById(5-i), dumb_move.DumbMove))

    def tick(
        self,
        world_state: stp.rc.WorldState,
    ) -> List[Tuple[int, RobotIntent]]:
        # returns list of (robot_id, robot_intent)

        # if not self.assigned_roles:
        # assumes all roles requested are filled, because tactic is one unit
        if len(self.assigned_roles) != len(self._role_requests):
            self.init_roles(world_state)

        return [(role.robot.id, role.tick(world_state)) for role in self.assigned_roles]

    def is_done(
        self,
        world_state: stp.rc.WorldState,
    ) -> bool:
        return all([role.is_done(world_state) for role in self.assigned_roles])

    def init_roles(
        self,
        world_state: stp.rc.WorldState,
    ):
        for i, robot in enumerate(self.assigned_robots):
            role = self._role_requests[i][1]
            pt = self.move_points[i]
            if role is dumb_move.DumbMove:
                self.assigned_roles.append(role(robot, pt, world_state.ball.pos))
<commit_msg>add todos to line tactic<commit_after>import stp
from rj_gameplay.role import dumb_move
from typing import List, Tuple

from rj_msgs.msg import RobotIntent

class LineTactic(stp.tactic.Tactic):
    """Tactic for line up play that puts all six robots in a line on the left of the field.
    """

    def __init__(self, world_state: stp.rc.WorldState):
        super().__init__(world_state)

        # compute move points
        # TODO: make start on side of the field, so this Tactic is actually useful during penalty situations
        start = (3.0, 0.0)
        dy = 0.5
        # TODO: make the # here a param instead of hardcoding for same reason as above TODO
        self.move_points = [(start[0], start[1] + i * dy) for i in range(6)]

        # request closest robot every pt
        for pt in self.move_points:
            # for some reason stp.role doesn't need to be imported?
            self._role_requests.append(
                (stp.role.cost.PickClosestRobot(pt), dumb_move.DumbMove)
            )

        # OR hardcode certain ids to go
        # for i, pt in enumerate(self.move_points):
        #     self._role_requests.append((stp.role.cost.PickRobotById(5-i), dumb_move.DumbMove))

    def tick(
        self,
        world_state: stp.rc.WorldState,
    ) -> List[Tuple[int, RobotIntent]]:
        # returns list of (robot_id, robot_intent)

        # if not self.assigned_roles:
        # assumes all roles requested are filled, because tactic is one unit
        if len(self.assigned_roles) != len(self._role_requests):
            self.init_roles(world_state)

        return [(role.robot.id, role.tick(world_state)) for role in self.assigned_roles]

    def is_done(
        self,
        world_state: stp.rc.WorldState,
    ) -> bool:
        return all([role.is_done(world_state) for role in self.assigned_roles])

    def init_roles(
        self,
        world_state: stp.rc.WorldState,
    ):
        for i, robot in enumerate(self.assigned_robots):
            role = self._role_requests[i][1]
            pt = self.move_points[i]
            if role is dumb_move.DumbMove:
                self.assigned_roles.append(role(robot, pt, world_state.ball.pos))
<|endoftext|>


<commit_before>import time
from monosat.bvtheory import BitVector
from monosat.logic import *
from monosat.monosat_c import Monosat
from monosat.pbtheory import PBManager

def FoundOptimal():
    return Monosat().lastSolutionWasOptimal();

def Solve(assumptions=None, preprocessing=True,bvs_to_minimize=None,time_limit_seconds=None, memory_limit_mb=None,conflict_limit=None):
    WriteConstraints()
    if time_limit_seconds is None or time_limit_seconds <=0:
        time_limit_seconds=-1
    if memory_limit_mb is None or memory_limit_mb <=0:
        memory_limit_mb=-1
    if conflict_limit is None or conflict_limit <=0:
        conflict_limit=-1

    Monosat().setTimeLimit(time_limit_seconds)
    Monosat().setMemoryLimit(memory_limit_mb)
    Monosat().setConflictLimit(conflict_limit)

    #if preprocessing:
    #    Monosat().preprocess();
    print("Solving in Monosat...")
    t = time.clock()

    if isinstance(assumptions,Var):
        assumptions=[assumptions]
    elif assumptions is None:
        assumptions = []

    if isinstance(bvs_to_minimize,BitVector):
        bvs_to_minimize=[bvs_to_minimize]
    elif bvs_to_minimize is None:
        bvs_to_minimize=[]

    for bv in bvs_to_minimize:
        bvID = bv.getID()
        Monosat().minimizeBV(bvID)

    r= Monosat().solveLimited([x.getLit() for x in assumptions])
    #Monosat().clearOptimizationObjectives();
    if r is None:
        raise RuntimeError("MonoSAT aborted before solving (possibly do to a time or memory limit)")
    Monosat().elapsed_time +=  time.clock()-t
    found_optimal = Monosat().lastSolutionWasOptimal();
    if r is None:
        raise RuntimeError("MonoSAT aborted before solving (possibly due to a time or memory limit)")
    elif r and not found_optimal:
        print("MonoSAT found a satisfying solution, but it might not be optimal (due to a time or memory limit)")

    return r
#If the most recent solve() call was UNSAT, returns a
def getConflictClause():
    conf_clause = Monosat().getConflictClause()
    if conf_clause is None:
        return None
    else:
        vars = []
        for v in conf_clause:
            vars.append(Var(v))
        return vars

#optimization support
def clearOptimizationObjectives():
    Monosat().clearOptimizationObjectives()

def maximize(bitvector_or_literals,weights=None):
    if isinstance(bitvector_or_literals,Var):
        arg = [bitvector_or_literals]
    if isinstance(weights,int):
        weights = [weights]

    if isinstance(bitvector_or_literals,BitVector):
        Monosat().maximizeBV(bitvector_or_literals.getID())
    else:
        lit_ints = [l.getLit() for l in bitvector_or_literals]
        if weights is None:
            Monosat().maximizeLits(lit_ints)
        else:
            Monosat().maximizeWeightedLits(lit_ints,weights)

def minimize(bitvector_or_literals,weights=None):
    if isinstance(bitvector_or_literals,Var):
        bitvector_or_literals = [bitvector_or_literals]
    if isinstance(weights,int):
        weights = [weights]

    if isinstance(bitvector_or_literals,int):
        Monosat().minimizeBV(bitvector_or_literals)
    else:
        lit_ints = [l.getLit() for l in bitvector_or_literals]
        if weights is None:
            Monosat().minimizeLits(lit_ints)
        else:
            Monosat().minimizeWeightedLits(lit_ints,weights)

def WriteConstraints():
    _writePBCosntraints()

def _writePBCosntraints():
    #write any pseudoboolean constraints
    if not PBManager().hasConstraints():
        return

    t = time.clock()
    pbmgr = PBManager()
    pbmgr.flush();
    d = time.clock()
    PBManager().elapsed_time += d-t<commit_msg>python api now throws "SolveException" on timeout, instead of RuntimeError<commit_after>import time
from monosat.bvtheory import BitVector
from monosat.logic import *
from monosat.monosat_c import Monosat
from monosat.pbtheory import PBManager

def FoundOptimal():
    return Monosat().lastSolutionWasOptimal();
class SolveException(Exception):
    pass
def Solve(assumptions=None, preprocessing=True,bvs_to_minimize=None,time_limit_seconds=None, memory_limit_mb=None,conflict_limit=None):
    WriteConstraints()
    if time_limit_seconds is None or time_limit_seconds <=0:
        time_limit_seconds=-1
    if memory_limit_mb is None or memory_limit_mb <=0:
        memory_limit_mb=-1
    if conflict_limit is None or conflict_limit <=0:
        conflict_limit=-1

    Monosat().setTimeLimit(time_limit_seconds)
    Monosat().setMemoryLimit(memory_limit_mb)
    Monosat().setConflictLimit(conflict_limit)

    #if preprocessing:
    #    Monosat().preprocess();
    print("Solving in Monosat...")
    t = time.clock()

    if isinstance(assumptions,Var):
        assumptions=[assumptions]
    elif assumptions is None:
        assumptions = []

    if isinstance(bvs_to_minimize,BitVector):
        bvs_to_minimize=[bvs_to_minimize]
    elif bvs_to_minimize is None:
        bvs_to_minimize=[]

    for bv in bvs_to_minimize:
        bvID = bv.getID()
        Monosat().minimizeBV(bvID)

    r= Monosat().solveLimited([x.getLit() for x in assumptions])
    #Monosat().clearOptimizationObjectives();
    if r is None:
        raise SolveException("MonoSAT aborted before solving (possibly do to a time or memory limit)")
    Monosat().elapsed_time +=  time.clock()-t
    found_optimal = Monosat().lastSolutionWasOptimal();
    if r is None:
        raise SolveException("MonoSAT aborted before solving (possibly due to a time or memory limit)")
    elif r and not found_optimal:
        print("MonoSAT found a satisfying solution, but it might not be optimal (due to a time or memory limit)")

    return r
#If the most recent solve() call was UNSAT, returns a
def getConflictClause():
    conf_clause = Monosat().getConflictClause()
    if conf_clause is None:
        return None
    else:
        vars = []
        for v in conf_clause:
            vars.append(Var(v))
        return vars

#optimization support
def clearOptimizationObjectives():
    Monosat().clearOptimizationObjectives()

def maximize(bitvector_or_literals,weights=None):
    if isinstance(bitvector_or_literals,Var):
        arg = [bitvector_or_literals]
    if isinstance(weights,int):
        weights = [weights]

    if isinstance(bitvector_or_literals,BitVector):
        Monosat().maximizeBV(bitvector_or_literals.getID())
    else:
        lit_ints = [l.getLit() for l in bitvector_or_literals]
        if weights is None:
            Monosat().maximizeLits(lit_ints)
        else:
            Monosat().maximizeWeightedLits(lit_ints,weights)

def minimize(bitvector_or_literals,weights=None):
    if isinstance(bitvector_or_literals,Var):
        bitvector_or_literals = [bitvector_or_literals]
    if isinstance(weights,int):
        weights = [weights]

    if isinstance(bitvector_or_literals,int):
        Monosat().minimizeBV(bitvector_or_literals)
    else:
        lit_ints = [l.getLit() for l in bitvector_or_literals]
        if weights is None:
            Monosat().minimizeLits(lit_ints)
        else:
            Monosat().minimizeWeightedLits(lit_ints,weights)

def WriteConstraints():
    _writePBCosntraints()

def _writePBCosntraints():
    #write any pseudoboolean constraints
    if not PBManager().hasConstraints():
        return

    t = time.clock()
    pbmgr = PBManager()
    pbmgr.flush();
    d = time.clock()
    PBManager().elapsed_time += d-t<|endoftext|>


<commit_before># git describe --tags
__version__ = "0.5.0-23-gf77c6b2"
<commit_msg>update version<commit_after># git describe --tags
__version__ = "0.5.0-48-g28ef3e3"
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from StringIO import StringIO
import csv

from openerp import models, fields, api, exceptions

class ChainImportWizard(models.TransientModel):
    _name = 'bestja.stores.chain_import'

    STATUS_OPTIONS = ('tak', 'nie')  # order: accepted, rejected

    def _default_project(self):
        stores = self.env['bestja_stores.store_in_project'].browse(self.env.context.get('active_ids'))
        return stores[0].top_project

    project = fields.Many2one(
        'bestja.project',
        string=u"Projekt",
        required=True,
        domain="[('enable_stores', '=', True), ('organization_level', '=', 0)]",
        default=_default_project,
    )
    chain = fields.Many2one(
        'bestja_stores.chain',
        string=u"Sieć Handlowa",
        required=True,
    )
    import_file = fields.Binary(required=True, string=u"Plik CSV")

    @api.multi
    def start_import(self):
        if not self.user_has_groups('bestja_base.instance_admin'):
            raise exceptions.AccessError("Nie masz uprawnień do tego importu!")

        csv_content = self.import_file.decode('base64')
        dialect = csv.Sniffer().sniff(csv_content)  # Try to guess the format
        rows = csv.reader(StringIO(csv_content), dialect)

        results = {}

        for line_no, row in enumerate(rows, start=1):
            try:
                row = [unicode(cell, 'utf-8') for cell in row]
            except UnicodeDecodeError:
                raise exceptions.ValidationError(
                    """Problem z kodowaniem znaku w linii {}.
                    Upewnij się, że plik CSV używa kodowania UTF-8""".format(line_no)
                )
            if len(row) < 2:
                continue

            chain_id = row[0].strip()
            status = row[1].strip().lower()
            reason = row[2].strip() if len(row) >= 3 else ""
            replacement_id = row[3].strip() if len(row) >= 4 else ""
            replacement_name = ""
            if len(row) >= 6 and row[4] and row[5]:
                replacement_name = u"{}, {}".format(row[4], row[5])

            if status not in ChainImportWizard.STATUS_OPTIONS:
                continue  # Unrecognised status

            rejected = (status == ChainImportWizard.STATUS_OPTIONS[1])

            stores = self.env['bestja_stores.store_in_project'].search([
                ('store.chain_id', '=', chain_id),
                ('top_project', '=', self.project.id),
                ('store.chain', '=', self.chain.id),
                ('state', '=', 'activated'),
            ])

            replacement_obj = None
            if replacement_id:
                replacement_obj = self.env['bestja_stores.store'].search([
                    ('chain_id', '=', replacement_id),
                    ('chain', '=', self.chain.id),
                ])

            for store in stores:
                if rejected:
                    store.sudo().write({
                        'state': 'deactivated',
                        'chain_decision': 'deactivated',
                        'time_deactivated': fields.Datetime.now(),
                        'time_decision': fields.Datetime.now(),
                        'rejection_reason': reason,
                        'rejection_replacement_id': replacement_id,
                        'rejection_replacement_address': replacement_name,
                    })
                else:
                    store.sudo().write({
                        'chain_decision': 'activated',
                        'time_decision': fields.Datetime.now(),
                    })

                store_dic = {
                    'store_obj': store,
                    'replacement_obj': replacement_obj,
                    'replacement_name': replacement_name,
                    'reason': reason,
                }

                project = store.project
                if project.id not in results:
                    results[project.id] = {
                        'project': project,
                        'accepted': [],
                        'rejected': [],
                    }
                results[project.id]['rejected' if rejected else 'accepted'].append(store_dic)

                # Add to Bank's report
                if project.organization_level == 2 and project.parent:
                    parent = project.parent
                    if parent.id not in results:
                        results[parent.id] = {
                            'project': parent,
                            'accepted': [],
                            'rejected': [],
                        }
                    results[parent.id]['rejected' if rejected else 'accepted'].append(store_dic)

        for _, result in results.iteritems():
            self.env.ref('bestja_stores_chain_import.project_raport').with_context(
                obj=self,
                accepted=result['accepted'],
                rejected=result['rejected'],
                organization=result['project'].organization,
            ).send(
                recipients=result['project'].responsible_user,
                sender=self.env.user,
            )
<commit_msg>Limit number of replacement stores in store import<commit_after># -*- coding: utf-8 -*-
from StringIO import StringIO
import csv

from openerp import models, fields, api, exceptions

class ChainImportWizard(models.TransientModel):
    _name = 'bestja.stores.chain_import'

    STATUS_OPTIONS = ('tak', 'nie')  # order: accepted, rejected

    def _default_project(self):
        stores = self.env['bestja_stores.store_in_project'].browse(self.env.context.get('active_ids'))
        return stores[0].top_project

    project = fields.Many2one(
        'bestja.project',
        string=u"Projekt",
        required=True,
        domain="[('enable_stores', '=', True), ('organization_level', '=', 0)]",
        default=_default_project,
    )
    chain = fields.Many2one(
        'bestja_stores.chain',
        string=u"Sieć Handlowa",
        required=True,
    )
    import_file = fields.Binary(required=True, string=u"Plik CSV")

    @api.multi
    def start_import(self):
        if not self.user_has_groups('bestja_base.instance_admin'):
            raise exceptions.AccessError("Nie masz uprawnień do tego importu!")

        csv_content = self.import_file.decode('base64')
        dialect = csv.Sniffer().sniff(csv_content)  # Try to guess the format
        rows = csv.reader(StringIO(csv_content), dialect)

        results = {}

        for line_no, row in enumerate(rows, start=1):
            try:
                row = [unicode(cell, 'utf-8') for cell in row]
            except UnicodeDecodeError:
                raise exceptions.ValidationError(
                    """Problem z kodowaniem znaku w linii {}.
                    Upewnij się, że plik CSV używa kodowania UTF-8""".format(line_no)
                )
            if len(row) < 2:
                continue

            chain_id = row[0].strip()
            status = row[1].strip().lower()
            reason = row[2].strip() if len(row) >= 3 else ""
            replacement_id = row[3].strip() if len(row) >= 4 else ""
            replacement_name = ""
            if len(row) >= 6 and row[4] and row[5]:
                replacement_name = u"{}, {}".format(row[4], row[5])

            if status not in ChainImportWizard.STATUS_OPTIONS:
                continue  # Unrecognised status

            rejected = (status == ChainImportWizard.STATUS_OPTIONS[1])

            stores = self.env['bestja_stores.store_in_project'].search([
                ('store.chain_id', '=', chain_id),
                ('top_project', '=', self.project.id),
                ('store.chain', '=', self.chain.id),
                ('state', '=', 'activated'),
            ])

            replacement_obj = None
            if replacement_id:
                replacement_obj = self.env['bestja_stores.store'].search([
                    ('chain_id', '=', replacement_id),
                    ('chain', '=', self.chain.id),
                ], limit=1)

            for store in stores:
                if rejected:
                    store.sudo().write({
                        'state': 'deactivated',
                        'chain_decision': 'deactivated',
                        'time_deactivated': fields.Datetime.now(),
                        'time_decision': fields.Datetime.now(),
                        'rejection_reason': reason,
                        'rejection_replacement_id': replacement_id,
                        'rejection_replacement_address': replacement_name,
                    })
                else:
                    store.sudo().write({
                        'chain_decision': 'activated',
                        'time_decision': fields.Datetime.now(),
                    })

                store_dic = {
                    'store_obj': store,
                    'replacement_obj': replacement_obj,
                    'replacement_name': replacement_name,
                    'reason': reason,
                }

                project = store.project
                if project.id not in results:
                    results[project.id] = {
                        'project': project,
                        'accepted': [],
                        'rejected': [],
                    }
                results[project.id]['rejected' if rejected else 'accepted'].append(store_dic)

                # Add to Bank's report
                if project.organization_level == 2 and project.parent:
                    parent = project.parent
                    if parent.id not in results:
                        results[parent.id] = {
                            'project': parent,
                            'accepted': [],
                            'rejected': [],
                        }
                    results[parent.id]['rejected' if rejected else 'accepted'].append(store_dic)

        for _, result in results.iteritems():
            self.env.ref('bestja_stores_chain_import.project_raport').with_context(
                obj=self,
                accepted=result['accepted'],
                rejected=result['rejected'],
                organization=result['project'].organization,
            ).send(
                recipients=result['project'].responsible_user,
                sender=self.env.user,
            )
<|endoftext|>


<commit_before>import collections

import requests
from django.contrib.auth import get_user_model

from nodeconductor.core.models import SshPublicKey

Coordinates = collections.namedtuple('Coordinates', ('latitude', 'longitude'))

class GeoIpException(Exception):
    pass

def serialize_ssh_key(ssh_key):
    return {
        'name': ssh_key.name,
        'user_id': ssh_key.user_id,
        'fingerprint': ssh_key.fingerprint,
        'public_key': ssh_key.public_key,
        'uuid': ssh_key.uuid.hex
    }

def deserialize_ssh_key(data):
    return SshPublicKey(
        name=data['name'],
        user_id=data['user_id'],
        fingerprint=data['fingerprint'],
        public_key=data['public_key'],
        uuid=data['uuid']
    )

def serialize_user(user):
    return {
        'username': user.username,
        'email': user.email
    }

def deserialize_user(data):
    return get_user_model()(
        username=data['username'],
        email=data['email']
    )

def get_coordinates_by_ip(ip_address):
    url = 'http://freegeoip.net/json/{}'.format(ip_address)

    response = requests.get(url)
    if response.ok:
        data = response.json()
        return Coordinates(latitude=data['latitude'],
                           longitude=data['longitude'])
    else:
        params = (url, response.status_code, response.text)
        raise GeoIpException("Request to geoip API %s failed: %s %s" % params)
<commit_msg>Convert requests exception to geoip exception (NC-1289)<commit_after>import collections

import requests
from django.contrib.auth import get_user_model

from nodeconductor.core.models import SshPublicKey

Coordinates = collections.namedtuple('Coordinates', ('latitude', 'longitude'))

class GeoIpException(Exception):
    pass

def serialize_ssh_key(ssh_key):
    return {
        'name': ssh_key.name,
        'user_id': ssh_key.user_id,
        'fingerprint': ssh_key.fingerprint,
        'public_key': ssh_key.public_key,
        'uuid': ssh_key.uuid.hex
    }

def deserialize_ssh_key(data):
    return SshPublicKey(
        name=data['name'],
        user_id=data['user_id'],
        fingerprint=data['fingerprint'],
        public_key=data['public_key'],
        uuid=data['uuid']
    )

def serialize_user(user):
    return {
        'username': user.username,
        'email': user.email
    }

def deserialize_user(data):
    return get_user_model()(
        username=data['username'],
        email=data['email']
    )

def get_coordinates_by_ip(ip_address):
    url = 'http://freegeoip.net/json/{}'.format(ip_address)

    try:
        response = requests.get(url)
    except requests.exceptions.RequestException as e:
        raise GeoIpException("Request to geoip API %s failed: %s" % (url, e))

    if response.ok:
        data = response.json()
        return Coordinates(latitude=data['latitude'],
                           longitude=data['longitude'])
    else:
        params = (url, response.status_code, response.text)
        raise GeoIpException("Request to geoip API %s failed: %s %s" % params)
<|endoftext|>


<commit_before>import codecs
from urllib.parse import urlparse

from nm_printing.base import Printer

class StarPrinter(Printer):
    def __init__(self, port):
        super(StarPrinter, self).__init__()

        self._port = port
        self._charset = 'ascii'

    def _op_set_charset(self, charset):
        charset = codecs.lookup(charset).name

        command = b'\x1b\x1d\x74' + {
            'ascii': b'\x00',  # TODO Normal is not ascii but something weird
            'euc_jp': b'\x02',  # TODO Katakana
            'cp437': b'\x03',
            'cp858': b'\x04',
            'cp852': b'\x05',
            'cp860': b'\x06',
            'cp861': b'\x07',
            'cp863': b'\x08',
            'cp865': b'\x09',
            'cp866': b'\x0a',
            'cp855': b'\x0b',
            'cp857': b'\x0c',
            'cp862': b'\x0d',
            'cp864': b'\x0e',
            'cp737': b'\x0f',
            'cp851': b'\x10',
            'cp869': b'\x11',
            'cp928': b'\x12',  # TODO not supported by python
            'cp772': b'\x13',  # TODO not supported by python
            'cp774': b'\x14',  # TODO not supported by python
            'cp874': b'\x15',
            'cp1252': b'\x20',
            'cp1250': b'\x21',
            'cp1251': b'\x22',
            'cp3840': b'\x40',  # TODO not supported by python
            'cp3841': b'\x41',  # TODO not supported by python
            'cp3843': b'\x42',  # TODO not supported by python
            'cp3844': b'\x43',  # TODO not supported by python
            'cp3845': b'\x44',  # TODO not supported by python
            'cp3846': b'\x45',  # TODO not supported by python
            'cp3847': b'\x46',  # TODO not supported by python
            'cp3848': b'\x47',  # TODO not supported by python
            'cp1001': b'\x48',  # TODO not supported by python
            'cp2001': b'\x49',  # TODO not supported by python
            'cp3001': b'\x4a',  # TODO not supported by python
            'cp3002': b'\x4b',  # TODO not supported by python
            'cp3011': b'\x4c',  # TODO not supported by python
            'cp3012': b'\x4d',  # TODO not supported by python
            'cp3021': b'\x4e',  # TODO not supported by python
            'cp3041': b'\x4f',  # TODO not supported by python
        }[charset]

        # XXX side-effect XXX
        # need to keep a record of what charset the printer is using in order
        # to encode input strings.
        # Might be better to set this only once when the printer is initialised
        self._charset = charset
        return command

    def _op_write_string(self, string):
        # TODO escaping
        return string.encode(self._charset)

    def compile_command(self, command):
        commands = {
            'select-bold': b'\x1b\x45',
            'cancel-bold': b'\x1b\x46',
            'select-highlight': b'\x1b\x34',
            'cancel-highlight': b'\x1b\x35',
            'select-inverse': b'\x0f',
            'cancel-inverse': b'\x12',
            'fontsize-small': b'\x1b\x14',
            'fontsize-medium': b'\x1b\x0e',
            'fontsize-large': b'\x1b\x68\x32',
            'set-charset': self._op_set_charset,
            'write': self._op_write_string,
            'cut-through': b'\x1b\x64\x02',
            'cut-partial': b'\x1b\x64\x03',
            'cut-through-immediate': b'\x1b\x64\x00',
            'cut-partial-immediate': b'\x1b\x64\x01',
        }
        if isinstance(command, str):
            command_name, args = command, []
        else:
            command_name, *args = command

        command = commands[command_name]
        if isinstance(command, bytes):
            return command
        return command(*args)

    def run_commands(self, commands):
        message = b''.join(
            self.compile_command(command) for command in commands
        )
        self._port.write(message)
        self._port.flush()

def open_tcp(uri, *args, **kwargs):
    raise NotImplementedError()

def open_lpt(uri, *args, **kwargs):
    uri_parts = urlparse(uri)
    port = open(uri_parts.path, 'r+b')

    return StarPrinter(port, *args, **kwargs)

def open_com(uri, *args, **kwargs):
    import serial

    uri_parts = urlparse(uri)
    port = serial.Serial(uri_parts.netloc)

    return StarPrinter(port, *args, **kwargs)

def open_debug(uri, *args, **kwargs):
    class DebugPort(object):
        def write(self, data):
            for line in data.split(b'\n'):
                print(repr(line))

        def flush(self):
            pass

    return StarPrinter(DebugPort(), *args, **kwargs)
<commit_msg>add reset command<commit_after>import codecs
from urllib.parse import urlparse

from nm_printing.base import Printer

class StarPrinter(Printer):
    def __init__(self, port):
        super(StarPrinter, self).__init__()

        self._port = port
        self._charset = 'ascii'

    def _op_set_charset(self, charset):
        charset = codecs.lookup(charset).name

        command = b'\x1b\x1d\x74' + {
            'ascii': b'\x00',  # TODO Normal is not ascii but something weird
            'euc_jp': b'\x02',  # TODO Katakana
            'cp437': b'\x03',
            'cp858': b'\x04',
            'cp852': b'\x05',
            'cp860': b'\x06',
            'cp861': b'\x07',
            'cp863': b'\x08',
            'cp865': b'\x09',
            'cp866': b'\x0a',
            'cp855': b'\x0b',
            'cp857': b'\x0c',
            'cp862': b'\x0d',
            'cp864': b'\x0e',
            'cp737': b'\x0f',
            'cp851': b'\x10',
            'cp869': b'\x11',
            'cp928': b'\x12',  # TODO not supported by python
            'cp772': b'\x13',  # TODO not supported by python
            'cp774': b'\x14',  # TODO not supported by python
            'cp874': b'\x15',
            'cp1252': b'\x20',
            'cp1250': b'\x21',
            'cp1251': b'\x22',
            'cp3840': b'\x40',  # TODO not supported by python
            'cp3841': b'\x41',  # TODO not supported by python
            'cp3843': b'\x42',  # TODO not supported by python
            'cp3844': b'\x43',  # TODO not supported by python
            'cp3845': b'\x44',  # TODO not supported by python
            'cp3846': b'\x45',  # TODO not supported by python
            'cp3847': b'\x46',  # TODO not supported by python
            'cp3848': b'\x47',  # TODO not supported by python
            'cp1001': b'\x48',  # TODO not supported by python
            'cp2001': b'\x49',  # TODO not supported by python
            'cp3001': b'\x4a',  # TODO not supported by python
            'cp3002': b'\x4b',  # TODO not supported by python
            'cp3011': b'\x4c',  # TODO not supported by python
            'cp3012': b'\x4d',  # TODO not supported by python
            'cp3021': b'\x4e',  # TODO not supported by python
            'cp3041': b'\x4f',  # TODO not supported by python
        }[charset]

        # XXX side-effect XXX
        # need to keep a record of what charset the printer is using in order
        # to encode input strings.
        # Might be better to set this only once when the printer is initialised
        self._charset = charset
        return command

    def _op_write_string(self, string):
        # TODO escaping
        return string.encode(self._charset)

    def compile_command(self, command):
        commands = {
            'reset': b'\x18',
            'select-bold': b'\x1b\x45',
            'cancel-bold': b'\x1b\x46',
            'select-highlight': b'\x1b\x34',
            'cancel-highlight': b'\x1b\x35',
            'select-inverse': b'\x0f',
            'cancel-inverse': b'\x12',
            'fontsize-small': b'\x1b\x14',
            'fontsize-medium': b'\x1b\x0e',
            'fontsize-large': b'\x1b\x68\x32',
            'set-charset': self._op_set_charset,
            'write': self._op_write_string,
            'cut-through': b'\x1b\x64\x02',
            'cut-partial': b'\x1b\x64\x03',
            'cut-through-immediate': b'\x1b\x64\x00',
            'cut-partial-immediate': b'\x1b\x64\x01',
        }
        if isinstance(command, str):
            command_name, args = command, []
        else:
            command_name, *args = command

        command = commands[command_name]
        if isinstance(command, bytes):
            return command
        return command(*args)

    def run_commands(self, commands):
        message = b''.join(
            self.compile_command(command) for command in commands
        )
        self._port.write(message)
        self._port.flush()

def open_tcp(uri, *args, **kwargs):
    raise NotImplementedError()

def open_lpt(uri, *args, **kwargs):
    uri_parts = urlparse(uri)
    port = open(uri_parts.path, 'r+b')

    return StarPrinter(port, *args, **kwargs)

def open_com(uri, *args, **kwargs):
    import serial

    uri_parts = urlparse(uri)
    port = serial.Serial(uri_parts.netloc)

    return StarPrinter(port, *args, **kwargs)

def open_debug(uri, *args, **kwargs):
    class DebugPort(object):
        def write(self, data):
            for line in data.split(b'\n'):
                print(repr(line))

        def flush(self):
            pass

    return StarPrinter(DebugPort(), *args, **kwargs)
<|endoftext|>


<commit_before>import cupy
from cupy import _core

_packbits_kernel = _core.ElementwiseKernel(
    'raw T myarray, raw int32 myarray_size', 'uint8 packed',
    '''for (int j = 0; j < 8; ++j) {
        int k = i * 8 + j;
        int bit = k < myarray_size && myarray[k] != 0;
        packed |= bit << (7 - j);
    }''',
    'cupy_packbits_kernel'
)

def packbits(myarray, bitorder='big'):
    """Packs the elements of a binary-valued array into bits in a uint8 array.
    This function currently does not support ``axis`` option.
    Args:
        myarray (cupy.ndarray): Input array.
    Returns:
        cupy.ndarray: The packed array.
        bitorder (str, optional): bit order to use when packing the array,
        allowed values are `'little'` and `'big'`. Defaults to `'big'`.
    .. note::
        When the input array is empty, this function returns a copy of it,
        i.e., the type of the output array is not necessarily always uint8.
        This exactly follows the NumPy's behaviour (as of version 1.11),
        alghough this is inconsistent to the documentation.
    .. seealso:: :func:`numpy.packbits`
    """
    if myarray.dtype.kind not in 'biu':
        raise TypeError(
            'Expected an input array of integer or boolean data type')

    if bitorder not in ['big', 'little']:
        raise ValueError("bitorder must be either 'big' or 'little'")

    myarray = myarray.ravel()
    packed_size = (myarray.size + 7) // 8
    packed = cupy.zeros((packed_size,), dtype=cupy.uint8)
    return _packbits_kernel(myarray, myarray.size, packed)

_unpackbits_kernel = {
    'big': _core.ElementwiseKernel(
    'raw uint8 myarray', 'T unpacked',
    'unpacked = (myarray[i / 8] >> (7 - i % 8)) & 1;',
    'cupy_unpackbits_kernel'
),
    'little': _core.ElementwiseKernel(
    'raw uint8 myarray', 'T unpacked',
    'unpacked = (myarray[i / 8] >> (i % 8)) & 1;',
    'cupy_unpackbits_kernel'
)}

def unpackbits(myarray, bitorder='big'):
    """Unpacks elements of a uint8 array into a binary-valued output array.
    This function currently does not support ``axis`` option.
    Args:
        myarray (cupy.ndarray): Input array.
        bitorder (str, optional): bit order to use when unpacking the array,
        allowed values are `'little'` and `'big'`. Defaults to `'big'`.
    Returns:
        cupy.ndarray: The unpacked array.
    .. seealso:: :func:`numpy.unpackbits`
    """
    if myarray.dtype != cupy.uint8:
        raise TypeError('Expected an input array of unsigned byte data type')

    if bitorder not in ['big', 'little']:
        raise ValueError("bitorder must be either 'big' or 'little'")

    unpacked = cupy.ndarray((myarray.size * 8), dtype=cupy.uint8)
    return _unpackbits_kernel[bitorder](myarray, unpacked)<commit_msg>implement the bitorder support<commit_after>import cupy
from cupy import _core

_packbits_kernel =  {
    'big': _core.ElementwiseKernel(
            'raw T myarray, raw int32 myarray_size', 'uint8 packed',
            '''for (int j = 0; j < 8; ++j) {
                int k = i * 8 + j;
                int bit = k < myarray_size && myarray[k] != 0;
                packed |= bit << (7 - j);
            }''',
            'cupy_packbits_kernel'
            ),
    'little': _core.ElementwiseKernel(
                'raw T myarray, raw int32 myarray_size', 'uint8 packed',
                '''for (int j = 0; j < 8; ++j) {
                    int k = i * 8 + j;
                    int bit = k < myarray_size && myarray[k] != 0;
                    packed |= bit << j;
                }''',
                'cupy_packbits_kernel'
                )
}

def packbits(myarray, bitorder='big'):
    """Packs the elements of a binary-valued array into bits in a uint8 array.
    This function currently does not support ``axis`` option.
    Args:
        myarray (cupy.ndarray): Input array.
    Returns:
        cupy.ndarray: The packed array.
        bitorder (str, optional): bit order to use when packing the array,
        allowed values are `'little'` and `'big'`. Defaults to `'big'`.
    .. note::
        When the input array is empty, this function returns a copy of it,
        i.e., the type of the output array is not necessarily always uint8.
        This exactly follows the NumPy's behaviour (as of version 1.11),
        alghough this is inconsistent to the documentation.
    .. seealso:: :func:`numpy.packbits`
    """
    if myarray.dtype.kind not in 'biu':
        raise TypeError(
            'Expected an input array of integer or boolean data type')

    if bitorder not in ['big', 'little']:
        raise ValueError("bitorder must be either 'big' or 'little'")

    myarray = myarray.ravel()
    packed_size = (myarray.size + 7) // 8
    packed = cupy.zeros((packed_size,), dtype=cupy.uint8)
    return _packbits_kernel[bitorder](myarray, myarray.size, packed)

_unpackbits_kernel = {
    'big': _core.ElementwiseKernel(
                'raw uint8 myarray', 'T unpacked',
                'unpacked = (myarray[i / 8] >> (7 - i % 8)) & 1;',
                'cupy_unpackbits_kernel'
            ),
    'little': _core.ElementwiseKernel(
                'raw uint8 myarray', 'T unpacked',
                'unpacked = (myarray[i / 8] >> (i % 8)) & 1;',
                'cupy_unpackbits_kernel'
            )
}

def unpackbits(myarray, bitorder='big'):
    """Unpacks elements of a uint8 array into a binary-valued output array.
    This function currently does not support ``axis`` option.
    Args:
        myarray (cupy.ndarray): Input array.
        bitorder (str, optional): bit order to use when unpacking the array,
        allowed values are `'little'` and `'big'`. Defaults to `'big'`.
    Returns:
        cupy.ndarray: The unpacked array.
    .. seealso:: :func:`numpy.unpackbits`
    """
    if myarray.dtype != cupy.uint8:
        raise TypeError('Expected an input array of unsigned byte data type')

    if bitorder not in ['big', 'little']:
        raise ValueError("bitorder must be either 'big' or 'little'")

    unpacked = cupy.ndarray((myarray.size * 8), dtype=cupy.uint8)
    return _unpackbits_kernel[bitorder](myarray, unpacked)<|endoftext|>


<commit_before>import datetime
import logging
import time
import pytz

from cumulusci.robotframework.pageobjects import ListingPage
from cumulusci.robotframework.pageobjects import pageobject
from locators import affiliations_locators
from locators import eda_lex_locators
from robot.api import logger
from robot.libraries.BuiltIn import BuiltIn
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

@pageobject("Listing", "hed__HEDA_Settings")
class EDASettingsPage(ListingPage):
    object_name = "hed__HEDA_Settings"

    @property
    def eda(self):
        return self.builtin.get_library_instance('EDA')

    @property
    def pageobjects(self):
        return self.builtin.get_library_instance("cumulusci.robotframework.PageObjects")

    def _is_current_page(self):
        """ Verify we are on the EDA Settings page
            by verifying that the header title is 'EDA Settings'
        """
        locator = affiliations_locators["header"]
        self.selenium.page_should_contain_element(
            locator,
            message="Header with text 'EDA Settings' is not available on the page"
        )

    def _go_to_page(self, filter_name=None):
        url_pattern = "{root}/lightning/n/{object}"
        name = self._object_name
        object_name = "{}{}".format(self.cumulusci.get_namespace_prefix(), name)
        url = url_pattern.format(root=self.cumulusci.org.lightning_base_url, object=object_name)
        self.selenium.go_to(url)
        self.salesforce.wait_until_loading_is_complete()
        self.eda.wait_for_locator("frame", "accessibility title")
        self.salesforce.select_frame_with_title("accessibility title")

    def _check_if_element_exists(self, xpath):
        """ Checks if the given xpath exists """
        elements = int(self.selenium.get_matching_xpath_count(xpath))
        return True if elements > 0 else False

    def verify_timezone(self):
        """ Verify that a timezone value exists
            there is currently an open bug on this,
            once fixed, the keyword needs to be modified to check for a specific timezone
        """
        self.selenium.page_should_contain_element(affiliations_locators["timezone"])
        self.builtin.log("Actual timezone isn't checked; waiting for bug to be fixed", "WARN")

    def verify_toast_message(self, value):
        """ Verifies the toast message """
        self.selenium.wait_until_page_contains_element(affiliations_locators["toast_message"].format(value))

    def place_in_view(self,locator):
        """ Scroll the field or object into the current view
            Examples:
            | =Function= | =argument= |
            | place_in_view | any locator |
            | self.place_in_view(affiliations_locators["header"]) | |
        """
        self.selenium.driver.execute_script(
            "arguments[0].scrollIntoView()",
            self.selenium.driver.find_element_by_xpath(locator)
        )

    def open_item(self, locator, error_message, capture_screen):
        """ Performs a wait until the element shows on the page, and clicks the element """
        self.selenium.wait_until_page_contains_element(
            locator,
            timeout=60,
            error=error_message
        )
        self.selenium.click_element(locator)
        if capture_screen:
            self.selenium.capture_page_screenshot()

    def go_to_affiliation_settings(self):
        self.open_item(
            affiliations_locators["affiliations_tab"],
            "Cannot find the Affiliations tab",
            False
        )
        self.open_item(
            affiliations_locators["affiliations_settings_tab"],
            "Cannot find the Settings tab in the Affiliations page",
            False
        )
        return

    def Click_button_on_location(self, button, page):
        """ Select the specified button from the page that is specified """
        self.selenium.wait_until_page_contains_element(
            page,
            timeout=60
        )
        self.open_item(
            page,
            "Cannot find {} ".format(page),
            True
        )
        self.selenium.click_button(button)

    def Enable_the_checkbox(self, title, tab, loc_checkbox, loc_checkbox_edit):
        """ Ensure that the specified checkbox is checked
            Set the checkbox if it is not set
            Do nothing if the checkbox is already set
        """

        self.selenium.wait_until_page_contains_element(
            tab,
            timeout=60
        )
        self.open_item(
            tab,
            "Cannot find {} tab".format(tab),
            False
        )

        # Checkbox needs to be marked as checked
        if self._check_if_element_exists(loc_checkbox):
            self.builtin.log("{} checkbox is checked.".format(title))
            return
        else:
            self.builtin.log(
                "{} checkbox is NOT checked.\n".format(title) +
                "Opening EDIT mode"
            )
            self.selenium.click_button("Edit")
            self.builtin.log("Setting the {} checkbox.".format(title))
            self.selenium.wait_until_page_contains_element(
                loc_checkbox_edit,
                timeout=60
            )
            self.selenium.driver.execute_script(
                "arguments[0].click()",
                self.selenium.driver.find_element_by_xpath(loc_checkbox_edit)
            )
            self.selenium.click_button("Save")
            self.eda.close_toast_message()
            self.builtin.log(
                "Checkbox for {} setting has been set.\n".format(title)
            )

    def Disable_the_checkbox(self, title, tab, loc_checkbox, loc_checkbox_edit):
        """ Ensure that the specified checkbox is NOT checked
            Uncheck the checkbox if it is checked
            Do nothing if the checkbox is already clear
        """

        self.selenium.wait_until_page_contains_element(
            tab,
            timeout=60
        )
        self.open_item(
            tab,
            "Cannot find {} tab".format(tab),
            False
        )

        # Checkbox needs to be unchecked
        if self._check_if_element_exists(loc_checkbox):
            self.builtin.log("{} checkbox is already clear.".format(title))
            return
        else:
            self.builtin.log(
                "{} checkbox is checked.\n" +
                "Opening EDIT mode"
            )
            self.selenium.click_button("Edit")
            self.builtin.log("Clearing the {} checkbox.".format(title))
            self.selenium.wait_until_page_contains_element(
                loc_checkbox_edit,
                timeout=60
            )
            self.selenium.driver.execute_script(
                "arguments[0].click()",
                self.selenium.driver.find_element_by_xpath(loc_checkbox_edit)
            )
            self.selenium.click_button("Save")
            self.eda.close_toast_message()
            self.builtin.log("{} checkbox has been cleared.".format(title))

    def process_default_values(self):
        """ Validate the default values for Affiliation Settings """

        self.open_item(
            affiliations_locators["affiliations_tab"],
            "Cannot find the Affiliations tab in EDA Settings",
            False)

        self.open_item(
            affiliations_locators["affiliations_settings_tab"],
            "Cannot find the Settings tab in Affiliations",
            False)

        # Verify the default values for the checkboxes
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_ert_validation"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_delete_rec_affl"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_specify_role_for_c_affl"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_copy_affl_end_date"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_copy_affl_start_date"])

        # Verify the default values for the dropdowns
        self.selenium.driver.find_element_by_xpath(affiliations_locators["affiliations_former"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["affiliations_student"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["affiliations_current"])
        return
<commit_msg>add missing documentation<commit_after>import datetime
import logging
import time
import pytz

from cumulusci.robotframework.pageobjects import ListingPage
from cumulusci.robotframework.pageobjects import pageobject
from locators import affiliations_locators
from locators import eda_lex_locators
from robot.api import logger
from robot.libraries.BuiltIn import BuiltIn
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

@pageobject("Listing", "hed__HEDA_Settings")
class EDASettingsPage(ListingPage):
    object_name = "hed__HEDA_Settings"

    @property
    def eda(self):
        return self.builtin.get_library_instance('EDA')

    @property
    def pageobjects(self):
        return self.builtin.get_library_instance("cumulusci.robotframework.PageObjects")

    def _is_current_page(self):
        """ Verify we are on the EDA Settings page
            by verifying that the header title is 'EDA Settings'
        """
        locator = affiliations_locators["header"]
        self.selenium.page_should_contain_element(
            locator,
            message="Header with text 'EDA Settings' is not available on the page"
        )

    def _go_to_page(self, filter_name=None):
        url_pattern = "{root}/lightning/n/{object}"
        name = self._object_name
        object_name = "{}{}".format(self.cumulusci.get_namespace_prefix(), name)
        url = url_pattern.format(root=self.cumulusci.org.lightning_base_url, object=object_name)
        self.selenium.go_to(url)
        self.salesforce.wait_until_loading_is_complete()
        self.eda.wait_for_locator("frame", "accessibility title")
        self.salesforce.select_frame_with_title("accessibility title")

    def _check_if_element_exists(self, xpath):
        """ Checks if the given xpath exists """
        elements = int(self.selenium.get_matching_xpath_count(xpath))
        return True if elements > 0 else False

    def verify_timezone(self):
        """ Verify that a timezone value exists
            there is currently an open bug on this,
            once fixed, the keyword needs to be modified to check for a specific timezone
        """
        self.selenium.page_should_contain_element(affiliations_locators["timezone"])
        self.builtin.log("Actual timezone isn't checked; waiting for bug to be fixed", "WARN")

    def verify_toast_message(self, value):
        """ Verifies the toast message """
        self.selenium.wait_until_page_contains_element(affiliations_locators["toast_message"].format(value))

    def place_in_view(self,locator):
        """ Scroll the field or object into the current view
            Examples:
            | =Function= | =argument= |
            | place_in_view | any locator |
            | self.place_in_view(affiliations_locators["header"]) | |
        """
        self.selenium.driver.execute_script(
            "arguments[0].scrollIntoView()",
            self.selenium.driver.find_element_by_xpath(locator)
        )

    def open_item(self, locator, error_message, capture_screen):
        """ Performs a wait until the element shows on the page, and clicks the element """
        self.selenium.wait_until_page_contains_element(
            locator,
            timeout=60,
            error=error_message
        )
        self.selenium.click_element(locator)
        if capture_screen:
            self.selenium.capture_page_screenshot()

    def go_to_affiliation_settings(self):
        """ Navigate to the Affiliations and Settings pages """
        self.open_item(
            affiliations_locators["affiliations_tab"],
            "Cannot find the Affiliations tab",
            False
        )
        self.open_item(
            affiliations_locators["affiliations_settings_tab"],
            "Cannot find the Settings tab in the Affiliations page",
            False
        )
        return

    def Click_button_on_location(self, button, page):
        """ Select the specified button from the page that is specified """
        self.selenium.wait_until_page_contains_element(
            page,
            timeout=60
        )
        self.open_item(
            page,
            "Cannot find {} ".format(page),
            True
        )
        self.selenium.click_button(button)

    def Enable_the_checkbox(self, title, tab, loc_checkbox, loc_checkbox_edit):
        """ Ensure that the specified checkbox is checked
            Set the checkbox if it is not set
            Do nothing if the checkbox is already set
        """

        self.selenium.wait_until_page_contains_element(
            tab,
            timeout=60
        )
        self.open_item(
            tab,
            "Cannot find {} tab".format(tab),
            False
        )

        # Checkbox needs to be marked as checked
        if self._check_if_element_exists(loc_checkbox):
            self.builtin.log("{} checkbox is checked.".format(title))
            return
        else:
            self.builtin.log(
                "{} checkbox is NOT checked.\n".format(title) +
                "Opening EDIT mode"
            )
            self.selenium.click_button("Edit")
            self.builtin.log("Setting the {} checkbox.".format(title))
            self.selenium.wait_until_page_contains_element(
                loc_checkbox_edit,
                timeout=60
            )
            self.selenium.driver.execute_script(
                "arguments[0].click()",
                self.selenium.driver.find_element_by_xpath(loc_checkbox_edit)
            )
            self.selenium.click_button("Save")
            self.eda.close_toast_message()
            self.builtin.log(
                "Checkbox for {} setting has been set.\n".format(title)
            )

    def Disable_the_checkbox(self, title, tab, loc_checkbox, loc_checkbox_edit):
        """ Ensure that the specified checkbox is NOT checked
            Uncheck the checkbox if it is checked
            Do nothing if the checkbox is already clear
        """

        self.selenium.wait_until_page_contains_element(
            tab,
            timeout=60
        )
        self.open_item(
            tab,
            "Cannot find {} tab".format(tab),
            False
        )

        # Checkbox needs to be unchecked
        if self._check_if_element_exists(loc_checkbox):
            self.builtin.log("{} checkbox is already clear.".format(title))
            return
        else:
            self.builtin.log(
                "{} checkbox is checked.\n" +
                "Opening EDIT mode"
            )
            self.selenium.click_button("Edit")
            self.builtin.log("Clearing the {} checkbox.".format(title))
            self.selenium.wait_until_page_contains_element(
                loc_checkbox_edit,
                timeout=60
            )
            self.selenium.driver.execute_script(
                "arguments[0].click()",
                self.selenium.driver.find_element_by_xpath(loc_checkbox_edit)
            )
            self.selenium.click_button("Save")
            self.eda.close_toast_message()
            self.builtin.log("{} checkbox has been cleared.".format(title))

    def process_default_values(self):
        """ Validate the default values for Affiliation Settings """

        self.open_item(
            affiliations_locators["affiliations_tab"],
            "Cannot find the Affiliations tab in EDA Settings",
            False)

        self.open_item(
            affiliations_locators["affiliations_settings_tab"],
            "Cannot find the Settings tab in Affiliations",
            False)

        # Verify the default values for the checkboxes
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_ert_validation"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_delete_rec_affl"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_specify_role_for_c_affl"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_copy_affl_end_date"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["un_copy_affl_start_date"])

        # Verify the default values for the dropdowns
        self.selenium.driver.find_element_by_xpath(affiliations_locators["affiliations_former"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["affiliations_student"])
        self.selenium.driver.find_element_by_xpath(affiliations_locators["affiliations_current"])
        return
<|endoftext|>