<commit_before>#!/usr/bin/env python2
import rospy
import math
import time
import actionlib
from actionlib_msgs.msg import GoalStatus

import humanoid_league_msgs.msg
import tf2_ros as tf2
from tf2_geometry_msgs import PointStamped
from humanoid_league_msgs.msg import BallRelative, GoalRelative, GameState, PlayAnimationGoal, PlayAnimationAction
from geometry_msgs.msg import Twist

class Behavior(object):
    def __init__(self):
        self.init_walking_time = 10
        self.rotation_threshold = math.radians(10)
        self.walking_rotation_scalar = 0.08
        self.moonwalk_rotation = -0.1
        self.walking_speed_forward = 0.06
        self.walking_speed_sideward = 0.06
        self.reach_ball_time = 5.0
        self.ball_position = (100,100)
        self.ball_distance = 100
        self.ball_angle = 0.0
        self.ball_age = 100
        self.goal_angle = 1.0
        self.goal_kick_threshold = math.radians(10)
        self.goal_in_front = False
        self.allow_to_move = False
        self.kick_behavior = True
        self.goal_behavior = False
        rospy.init_node('backup_backup_behavior')

        self.tf_buffer = tf2.Buffer(cache_time=rospy.Duration(5))
        self.tf_listener = tf2.TransformListener(self.tf_buffer)

        self.anim = Anim()

        # Subscribe to 'ball_relative'-message
        self.ball_relative_msg = rospy.Subscriber(
            'ball_relative',
            BallRelative,
            self.ball_relative_cb,
            queue_size=1,
            tcp_nodelay=True)
        '''
        self.goal_relative_msg = rospy.Subscriber(
            'goal_relative',
            GoalRelative,
            self.goal_relative_cb,
            queue_size=1,
            tcp_nodelay=True)
        '''
        self.game_control_msg = rospy.Subscriber(
            'gamestate',
            GameState,
            self.gamestate_cb,
            queue_size=1,
            tcp_nodelay=True)

        self.pub_walking = rospy.Publisher(
            'cmd_vel',
            Twist,
            queue_size=1)

    def gamestate_cb(self, msg):
        self.allow_to_move = msg.allowedToMove

    def goal_relative_cb(self, msg):
        goal_obj = PointStamped(msg.header, msg.center_direction)
        x, y = self.get_ball_position_uv(goal_obj)
        goal_position = (float(x), float(y))
        self.goal_angle = math.atan2(float(goal_position[1]),float(goal_position[0]))
        if abs(self.goal_angle) < self.goal_kick_threshold:
            self.goal_in_front = True
        else:
            self.goal_in_front = False

    def ball_relative_cb(self, msg):
        ball_obj = PointStamped(msg.header, msg.ball_relative)
        x, y = self.get_ball_position_uv(ball_obj)
        self.ball_position = (float(x), float(y))
        self.ball_distance = math.sqrt(float(self.ball_position[0])**2 + float(self.ball_position[1])**2)
        self.ball_angle = math.atan2(float(self.ball_position[1]),float(self.ball_position[0]))
        self.ball_age = time.time()

    def get_ball_position_uv(self, ball):
        try:
            ball = self.tf_buffer.transform(ball, 'base_footprint', timeout=rospy.Duration(0.3))
        except (tf2.ConnectivityException, tf2.LookupException, tf2.ExtrapolationException) as e:
            rospy.logwarn(e)
            return None
        return ball.point.x, ball.point.y

    def start(self):
        self.behave()

    def behave(self):
        self.stopAtBegin()
        while self.allow_to_move == False and not rospy.is_shutdown():
            time.sleep(0.1)
            print("Waiting for game to start")
        self.walkIn()
        # Start normal behavior
        while not rospy.is_shutdown():
            self.searchBall()
            self.turnToBall()
            self.goToBall()
            if self.goal_behavior:
                self.moonWalk()
            if self.kick_behavior:
                self.kick()
            else:
                self.runThroughBall()
            time.sleep(1)

    def stopAtBegin(self):
        time.sleep(1)
        self.walkingWalkSteeredForward(0.0, 0.0)

    def walkIn(self):
        print("Walking into the field")
        self.walkingWalkSteeredForward(self.walking_speed_forward, 0)
        time.sleep(self.init_walking_time)
        self.walkingWalkSteeredForward(0, 0)
        time.sleep(1)

    def goToBall(self):
        while self.ball_distance > 0.5 and not rospy.is_shutdown():
            self.searchBall()
            self.turnToBall()
            print("Walking to ball")
            self.walkingWalkSteeredForward(self.walking_speed_forward, self.ball_angle * self.walking_rotation_scalar)
            time.sleep(0.5)
        print("Print reached ball")

    def searchBall(self):
        while not self.ball_seen() and not rospy.is_shutdown():
            print("Searching for ball")
            self.walkingTurn(self.walking_rotation_scalar * math.pi)
            time.sleep(0.5)

    def turnToBall(self):
        ball_angle = self.ball_angle
        delta = abs(ball_angle)
        while delta > self.rotation_threshold and not rospy.is_shutdown():
            print("Rotating to Ball....")
            direction = ball_angle/(delta+0.0000001)

            rotation = direction * self.walking_rotation_scalar * math.pi
            self.walkingTurn(rotation)
            time.sleep(0.5)
            ball_angle = self.ball_angle
            delta = abs(ball_angle)
        print("Right direction")

    def moonWalk(self):
        while not self.goal_in_front and not rospy.is_shutdown():
            direction = -(self.goal_angle/abs(self.goal_angle + 0.00001))
            self.walkingWalkSteeredSidewards(direction * self.walking_speed_sideward, direction* self.moonwalk_rotation)
        print("Goal Found")

    def ball_seen(self):
        return (time.time() - self.ball_age) < 1

    def stopWalking(self):
        walking_message = Twist()
        self.pub_walking.publish(walking_message)

    def walkingTurn(self, rate):
        if not self.allow_to_move:
            self.stopWalking()
            return
        walking_message = Twist()
        walking_message.angular.z = rate
        self.pub_walking.publish(walking_message)

    def walkingWalkSteeredForward(self, speed, rotation):
        if not self.allow_to_move:
            self.stopWalking()
            return
        walking_message = Twist()
        walking_message.angular.z = rotation
        walking_message.linear.x = speed
        self.pub_walking.publish(walking_message)

    def walkingWalkSteeredSidewards(self, speed, rotation):
        if not self.allow_to_move:
            self.stopWalking()
            return
        walking_message = Twist()
        walking_message.angular.z = rotation
        walking_message.linear.y = speed
        self.pub_walking.publish(walking_message)

    def kick(self):
        self.walkingWalkSteeredForward(self.walking_speed_forward,0)
        time.sleep(self.reach_ball_time)
        self.walkingWalkSteeredForward(0.0, 0.0)
        time.sleep(1)
        print("Kick")
        if self.ball_position[1] > 0:
            print("Left")
            animation = "kick_left"
        else:
            print("Right")
            animation = "kick_right"
        try:
            self.anim.anim_run(anim=animation)
            self.anim = Anim()
        except:
            print("Animation error")
        print("Finished kick")

    def runThroughBall(self):
        print("Run through ball")
        self.walkingWalkSteeredForward(self.walking_speed_forward,0)
        time.sleep(self.reach_ball_time)
        self.walkingWalkSteeredForward(0.0, 0.0)
        time.sleep(2)
        self.walkingWalkSteeredForward(- 0.8 * self.walking_speed_forward,0)
        time.sleep(self.reach_ball_time)
        self.walkingWalkSteeredForward(0.0, 0.0)
        time.sleep(1)

    def cb_unset_is_busy(self, _p1, _p2):
        self.busy_animation = False

class Anim(object):
    def __init__(self):
        pass

    def anim_run(self, anim=None):
        anim_client = actionlib.SimpleActionClient('animation', humanoid_league_msgs.msg.PlayAnimationAction)
        if anim is None:
            anim = rospy.get_param("~anim")
        if anim is None or anim == "":
            rospy.logwarn("Tried to play an animation with an empty name!")
            return False
        first_try = anim_client.wait_for_server(
            rospy.Duration(rospy.get_param("hcm/anim_server_wait_time", 10)))
        if not first_try:
            rospy.logerr(
                "Animation Action Server not running! Motion can not work without animation action server. "
                "Will now wait until server is accessible!")
            anim_client.wait_for_server()
            rospy.logwarn("Animation server now running, hcm will go on.")
        goal = humanoid_league_msgs.msg.PlayAnimationGoal()
        goal.animation = anim
        goal.hcm = False
        state = anim_client.send_goal_and_wait(goal)
        if state == GoalStatus.PENDING:
            print('Pending')
        elif state == GoalStatus.ACTIVE:
            print('Active')
        elif state == GoalStatus.PREEMPTED:
            print('Preempted')
        elif state == GoalStatus.SUCCEEDED:
            print('Succeeded')
        elif state == GoalStatus.ABORTED:
            print('Aborted')
        elif state == GoalStatus.REJECTED:
            print('Rejected')
        elif state == GoalStatus.PREEMPTING:
            print('Preempting')
        elif state == GoalStatus.RECALLING:
            print('Recalling')
        elif state == GoalStatus.RECALLED:
            print('Recalled')
        elif state == GoalStatus.LOST:
            print('Lost')
        else:
            print('Unknown state', state)

if __name__ == "__main__":
    behave = Behavior()
    behave.start()
<commit_msg>backup_behavior: update config values<commit_after>#!/usr/bin/env python2
import rospy
import math
import time
import actionlib
from actionlib_msgs.msg import GoalStatus

import humanoid_league_msgs.msg
import tf2_ros as tf2
from tf2_geometry_msgs import PointStamped
from humanoid_league_msgs.msg import BallRelative, GoalRelative, GameState, PlayAnimationGoal, PlayAnimationAction
from geometry_msgs.msg import Twist

class Behavior(object):
    def __init__(self):
        self.init_walking_time = 15
        self.rotation_threshold = math.radians(10)
        self.walking_rotation_scalar = 0.09
        self.moonwalk_rotation = -0.1
        self.walking_speed_forward = 0.06
        self.walking_speed_sideward = 0.06
        self.reach_ball_time = 5.0
        self.ball_position = (100,100)
        self.ball_distance = 100
        self.ball_angle = 0.0
        self.ball_age = 100
        self.goal_angle = 1.0
        self.goal_kick_threshold = math.radians(10)
        self.goal_in_front = False
        self.allow_to_move = False
        self.kick_behavior = False
        self.goal_behavior = False
        rospy.init_node('backup_backup_behavior')

        self.tf_buffer = tf2.Buffer(cache_time=rospy.Duration(5))
        self.tf_listener = tf2.TransformListener(self.tf_buffer)

        self.anim = Anim()

        # Subscribe to 'ball_relative'-message
        self.ball_relative_msg = rospy.Subscriber(
            'ball_relative',
            BallRelative,
            self.ball_relative_cb,
            queue_size=1,
            tcp_nodelay=True)
        '''
        self.goal_relative_msg = rospy.Subscriber(
            'goal_relative',
            GoalRelative,
            self.goal_relative_cb,
            queue_size=1,
            tcp_nodelay=True)
        '''
        self.game_control_msg = rospy.Subscriber(
            'gamestate',
            GameState,
            self.gamestate_cb,
            queue_size=1,
            tcp_nodelay=True)

        self.pub_walking = rospy.Publisher(
            'cmd_vel',
            Twist,
            queue_size=1)

    def gamestate_cb(self, msg):
        self.allow_to_move = msg.allowedToMove

    def goal_relative_cb(self, msg):
        goal_obj = PointStamped(msg.header, msg.center_direction)
        x, y = self.get_ball_position_uv(goal_obj)
        goal_position = (float(x), float(y))
        self.goal_angle = math.atan2(float(goal_position[1]),float(goal_position[0]))
        if abs(self.goal_angle) < self.goal_kick_threshold:
            self.goal_in_front = True
        else:
            self.goal_in_front = False

    def ball_relative_cb(self, msg):
        ball_obj = PointStamped(msg.header, msg.ball_relative)
        x, y = self.get_ball_position_uv(ball_obj)
        self.ball_position = (float(x), float(y))
        self.ball_distance = math.sqrt(float(self.ball_position[0])**2 + float(self.ball_position[1])**2)
        self.ball_angle = math.atan2(float(self.ball_position[1]),float(self.ball_position[0]))
        self.ball_age = time.time()

    def get_ball_position_uv(self, ball):
        try:
            ball = self.tf_buffer.transform(ball, 'base_footprint', timeout=rospy.Duration(0.3))
        except (tf2.ConnectivityException, tf2.LookupException, tf2.ExtrapolationException) as e:
            rospy.logwarn(e)
            return None
        return ball.point.x, ball.point.y

    def start(self):
        self.behave()

    def behave(self):
        self.stopAtBegin()
        while self.allow_to_move == False and not rospy.is_shutdown():
            time.sleep(0.1)
            print("Waiting for game to start")
        self.walkIn()
        # Start normal behavior
        while not rospy.is_shutdown():
            self.searchBall()
            self.turnToBall()
            self.goToBall()
            if self.goal_behavior:
                self.moonWalk()
            if self.kick_behavior:
                self.kick()
            else:
                self.runThroughBall()
            time.sleep(1)

    def stopAtBegin(self):
        time.sleep(1)
        self.walkingWalkSteeredForward(0.0, 0.0)

    def walkIn(self):
        print("Walking into the field")
        self.walkingWalkSteeredForward(self.walking_speed_forward, 0)
        time.sleep(self.init_walking_time)
        self.walkingWalkSteeredForward(0, 0)
        time.sleep(1)

    def goToBall(self):
        while self.ball_distance > 0.5 and not rospy.is_shutdown():
            self.searchBall()
            self.turnToBall()
            print("Walking to ball")
            self.walkingWalkSteeredForward(self.walking_speed_forward, self.ball_angle * self.walking_rotation_scalar)
            time.sleep(0.5)
        print("Print reached ball")

    def searchBall(self):
        while not self.ball_seen() and not rospy.is_shutdown():
            print("Searching for ball")
            self.walkingTurn(self.walking_rotation_scalar * math.pi)
            time.sleep(0.5)

    def turnToBall(self):
        ball_angle = self.ball_angle
        delta = abs(ball_angle)
        while delta > self.rotation_threshold and not rospy.is_shutdown():
            print("Rotating to Ball....")
            direction = ball_angle/(delta+0.0000001)

            rotation = direction * self.walking_rotation_scalar * math.pi
            self.walkingTurn(rotation)
            time.sleep(0.5)
            ball_angle = self.ball_angle
            delta = abs(ball_angle)
        print("Right direction")

    def moonWalk(self):
        while not self.goal_in_front and not rospy.is_shutdown():
            direction = -(self.goal_angle/abs(self.goal_angle + 0.00001))
            self.walkingWalkSteeredSidewards(direction * self.walking_speed_sideward, direction* self.moonwalk_rotation)
        print("Goal Found")

    def ball_seen(self):
        return (time.time() - self.ball_age) < 1

    def stopWalking(self):
        walking_message = Twist()
        self.pub_walking.publish(walking_message)

    def walkingTurn(self, rate):
        if not self.allow_to_move:
            self.stopWalking()
            return
        walking_message = Twist()
        walking_message.angular.z = rate
        self.pub_walking.publish(walking_message)

    def walkingWalkSteeredForward(self, speed, rotation):
        if not self.allow_to_move:
            self.stopWalking()
            return
        walking_message = Twist()
        walking_message.angular.z = rotation
        walking_message.linear.x = speed
        self.pub_walking.publish(walking_message)

    def walkingWalkSteeredSidewards(self, speed, rotation):
        if not self.allow_to_move:
            self.stopWalking()
            return
        walking_message = Twist()
        walking_message.angular.z = rotation
        walking_message.linear.y = speed
        self.pub_walking.publish(walking_message)

    def kick(self):
        self.walkingWalkSteeredForward(self.walking_speed_forward,0)
        time.sleep(self.reach_ball_time)
        self.walkingWalkSteeredForward(0.0, 0.0)
        time.sleep(1)
        print("Kick")
        if self.ball_position[1] > 0:
            print("Left")
            animation = "kick_left"
        else:
            print("Right")
            animation = "kick_right"
        try:
            self.anim.anim_run(anim=animation)
            self.anim = Anim()
        except:
            print("Animation error")
        print("Finished kick")

    def runThroughBall(self):
        print("Run through ball")
        self.walkingWalkSteeredForward(self.walking_speed_forward,0)
        time.sleep(self.reach_ball_time)
        self.walkingWalkSteeredForward(0.0, 0.0)
        time.sleep(2)
        self.walkingWalkSteeredForward(- 0.8 * self.walking_speed_forward,0)
        time.sleep(self.reach_ball_time)
        self.walkingWalkSteeredForward(0.0, 0.0)
        time.sleep(1)

    def cb_unset_is_busy(self, _p1, _p2):
        self.busy_animation = False

class Anim(object):
    def __init__(self):
        pass

    def anim_run(self, anim=None):
        anim_client = actionlib.SimpleActionClient('animation', humanoid_league_msgs.msg.PlayAnimationAction)
        if anim is None:
            anim = rospy.get_param("~anim")
        if anim is None or anim == "":
            rospy.logwarn("Tried to play an animation with an empty name!")
            return False
        first_try = anim_client.wait_for_server(
            rospy.Duration(rospy.get_param("hcm/anim_server_wait_time", 10)))
        if not first_try:
            rospy.logerr(
                "Animation Action Server not running! Motion can not work without animation action server. "
                "Will now wait until server is accessible!")
            anim_client.wait_for_server()
            rospy.logwarn("Animation server now running, hcm will go on.")
        goal = humanoid_league_msgs.msg.PlayAnimationGoal()
        goal.animation = anim
        goal.hcm = False
        state = anim_client.send_goal_and_wait(goal)
        if state == GoalStatus.PENDING:
            print('Pending')
        elif state == GoalStatus.ACTIVE:
            print('Active')
        elif state == GoalStatus.PREEMPTED:
            print('Preempted')
        elif state == GoalStatus.SUCCEEDED:
            print('Succeeded')
        elif state == GoalStatus.ABORTED:
            print('Aborted')
        elif state == GoalStatus.REJECTED:
            print('Rejected')
        elif state == GoalStatus.PREEMPTING:
            print('Preempting')
        elif state == GoalStatus.RECALLING:
            print('Recalling')
        elif state == GoalStatus.RECALLED:
            print('Recalled')
        elif state == GoalStatus.LOST:
            print('Lost')
        else:
            print('Unknown state', state)

if __name__ == "__main__":
    behave = Behavior()
    behave.start()
<|endoftext|>


<commit_before>from os.path import join, basename

from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.db import models, IntegrityError
from django.db.models.base import ModelBase
from django.template.defaultfilters import slugify

class BaseHtmlImageMetaclass(ModelBase):
    def __unicode__(self):
        return unicode(self.__name__)

class BaseHtmlImage(models.Model):
    """
    Basic abstract model. Derrive from me, include desired mixins.

    """
    __metaclass__ = BaseHtmlImageMetaclass

    UNOWNED_IMAGES_DIRECTORY = 'html-images'

    alt = models.CharField(max_length=80, blank=True)

    # 'width' and 'height' are object properties, not actual db fields
    image = models.ImageField(width_field='width', height_field='height',
            upload_to=lambda inst,fn: inst.upload_to(fn))

    class Meta:
        abstract = True

    def __unicode__(self):
        try:
            return basename(self.image.path)
        except ValueError:
            return u'{0} (no image file)'.format(type(self), fn)

    @property
    def alt_display(self):
        return self.alt

    _width = None
    def _get_width(self):
        return self._width
    def _set_width(self, val):
        self._width = val
    width = property(_get_width, _set_width)

    _height = None
    def _get_height(self):
        return self._height
    def _set_height(self, val):
        self._height = val
    height = property(_get_height, _set_height)

    def upload_to(self, org_filename):
        return join(self.UNOWNED_IMAGES_DIRECTORY, org_filename)

class OwnedImageMixin(object):
    """
    Use this mixin with BaseHtmlImage and OwnedImageToOneField with a
    field name of self.owner_field_name.

    Override owner_directory_name and image_directory_name to customize
    where images are stored in the filesystem.  Images will be stored in:

    MEDIA_ROOT/owner_directory_name/owner.pk/image_directory_name/org_filename

    """
    owner_field_name = 'owner'

    def __init__(self, *args, **kwargs):
        super(OwnedImageMixin, self).__init__(*args, **kwargs)
        owner_field = self._meta.get_field(self.owner_field_name)
        if not isinstance(owner_field, models.ForeignKey):
            m = u"Must be connected to owner via a related field with name specified in self.owner_field_name (currently configured as '{0}').".format(self.owner_field_name)
            raise ImproperlyConfigured(m)

    @property
    def alt_display(self):
        """
        If alt is explicitly specified in the DB, use that.  Elsewise, use the
        unicode() of the owner.
        """
        return super(OwnedImageMixin, self).alt_display or \
                unicode(getattr(self, self.owner_field_name))

    @property
    def image_directory_name(self):
        return slugify(self._meta.verbose_name)

    @property
    def owner_directory_name(self):
        return slugify(self.owner._meta.verbose_name_plural)

    def upload_to(self, org_filename):
        owner = getattr(self, self.owner_field_name)
        if owner.pk is None:
            m = u"Cannot determine where to put {0} instance's image file.  Owner has no primary key... save() owner to generate one.".format(type(self))
            raise IntegrityError(m)
        return join(
                self.owner_directory_name, unicode(owner.pk),
                self.image_directory_name, org_filename)

class OwnedImageToOneField(models.OneToOneField):
    """Related field from a OwnedImage to owner"""
    def __init__(self, *args, **kwargs):
        disallowed_args = ('blank', 'null')
        for arg in disallowed_args:
            if kwargs.has_key(arg):
                m = u"Cannot set {0} kwarg on {1}".format(arg, type(self))
                raise ImproperlyConfigured(m)
        kwargs.update({
            'blank': False,
            'null': False,
        })
        super(OwnedImageToOneField, self).__init__(*args, **kwargs)

class SizedImageMixin(object):
    """
    Use this mixin with BaseHtmlImage to validate images to specific sizes.
    Override MIN_WIDTH, MAX_WIDTH, MIN_HEIGHT, and MAX_HEIGHT to
    constrain image sizes.

    """
    MIN_WIDTH = None
    MAX_WIDTH = None
    MIN_HEIGHT = None
    MAX_HEIGHT = None

    def clean(self):
        mf = u"Image {0} too {1} ({2:n}px given, {3} allowed: {4:n}px)"
        if self.MIN_WIDTH is not None and self.width < self.MIN_WIDTH:
            m = mf.format('width', 'small', self.width, 'min', self.MIN_WIDTH)
            raise ValidationError(m)
        if self.MAX_WIDTH is not None and self.width > self.MAX_WIDTH:
            m = mf.format('width', 'large', self.width, 'max', self.MAX_WIDTH)
            raise ValidationError(m)
        if self.MIN_HEIGHT is not None and self.height < self.MIN_HEIGHT:
            m = mf.format(
                    'height', 'small', self.height, 'min', self.MIN_HEIGHT)
            raise ValidationError(m)
        if self.MAX_HEIGHT is not None and self.height > self.MAX_HEIGHT:
            m = mf.format(
                    'height', 'large', self.height, 'max', self.MAX_HEIGHT)
            raise ValidationError(m)
<commit_msg>clean - call super as well<commit_after>from os.path import join, basename

from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.db import models, IntegrityError
from django.db.models.base import ModelBase
from django.template.defaultfilters import slugify

class BaseHtmlImageMetaclass(ModelBase):
    def __unicode__(self):
        return unicode(self.__name__)

class BaseHtmlImage(models.Model):
    """
    Basic abstract model. Derrive from me, include desired mixins.

    """
    __metaclass__ = BaseHtmlImageMetaclass

    UNOWNED_IMAGES_DIRECTORY = 'html-images'

    alt = models.CharField(max_length=80, blank=True)

    # 'width' and 'height' are object properties, not actual db fields
    image = models.ImageField(width_field='width', height_field='height',
            upload_to=lambda inst,fn: inst.upload_to(fn))

    class Meta:
        abstract = True

    def __unicode__(self):
        try:
            return basename(self.image.path)
        except ValueError:
            return u'{0} (no image file)'.format(type(self), fn)

    @property
    def alt_display(self):
        return self.alt

    _width = None
    def _get_width(self):
        return self._width
    def _set_width(self, val):
        self._width = val
    width = property(_get_width, _set_width)

    _height = None
    def _get_height(self):
        return self._height
    def _set_height(self, val):
        self._height = val
    height = property(_get_height, _set_height)

    def upload_to(self, org_filename):
        return join(self.UNOWNED_IMAGES_DIRECTORY, org_filename)

class OwnedImageMixin(object):
    """
    Use this mixin with BaseHtmlImage and OwnedImageToOneField with a
    field name of self.owner_field_name.

    Override owner_directory_name and image_directory_name to customize
    where images are stored in the filesystem.  Images will be stored in:

    MEDIA_ROOT/owner_directory_name/owner.pk/image_directory_name/org_filename

    """
    owner_field_name = 'owner'

    def __init__(self, *args, **kwargs):
        super(OwnedImageMixin, self).__init__(*args, **kwargs)
        owner_field = self._meta.get_field(self.owner_field_name)
        if not isinstance(owner_field, models.ForeignKey):
            m = u"Must be connected to owner via a related field with name specified in self.owner_field_name (currently configured as '{0}').".format(self.owner_field_name)
            raise ImproperlyConfigured(m)

    @property
    def alt_display(self):
        """
        If alt is explicitly specified in the DB, use that.  Elsewise, use the
        unicode() of the owner.
        """
        return super(OwnedImageMixin, self).alt_display or \
                unicode(getattr(self, self.owner_field_name))

    @property
    def image_directory_name(self):
        return slugify(self._meta.verbose_name)

    @property
    def owner_directory_name(self):
        return slugify(self.owner._meta.verbose_name_plural)

    def upload_to(self, org_filename):
        owner = getattr(self, self.owner_field_name)
        if owner.pk is None:
            m = u"Cannot determine where to put {0} instance's image file.  Owner has no primary key... save() owner to generate one.".format(type(self))
            raise IntegrityError(m)
        return join(
                self.owner_directory_name, unicode(owner.pk),
                self.image_directory_name, org_filename)

class OwnedImageToOneField(models.OneToOneField):
    """
    Related field from a OwnedImage to owner

    """
    def __init__(self, *args, **kwargs):
        disallowed_args = ('blank', 'null')
        for arg in disallowed_args:
            if kwargs.has_key(arg):
                m = u"Cannot set {0} kwarg on {1}".format(arg, type(self))
                raise ImproperlyConfigured(m)
        kwargs.update({
            'blank': False,
            'null': False,
        })
        super(OwnedImageToOneField, self).__init__(*args, **kwargs)

class SizedImageMixin(object):
    """
    Use this mixin with BaseHtmlImage to validate images to specific sizes.
    Override MIN_WIDTH, MAX_WIDTH, MIN_HEIGHT, and MAX_HEIGHT to
    constrain image sizes.

    """
    MIN_WIDTH = None
    MAX_WIDTH = None
    MIN_HEIGHT = None
    MAX_HEIGHT = None

    def clean(self):
        super(SizedImageMixin, self).clean()
        mf = u"Image {0} too {1} ({2:n}px given, {3} allowed: {4:n}px)"
        if self.MIN_WIDTH is not None and self.width < self.MIN_WIDTH:
            m = mf.format('width', 'small', self.width, 'min', self.MIN_WIDTH)
            raise ValidationError(m)
        if self.MAX_WIDTH is not None and self.width > self.MAX_WIDTH:
            m = mf.format('width', 'large', self.width, 'max', self.MAX_WIDTH)
            raise ValidationError(m)
        if self.MIN_HEIGHT is not None and self.height < self.MIN_HEIGHT:
            m = mf.format(
                    'height', 'small', self.height, 'min', self.MIN_HEIGHT)
            raise ValidationError(m)
        if self.MAX_HEIGHT is not None and self.height > self.MAX_HEIGHT:
            m = mf.format(
                    'height', 'large', self.height, 'max', self.MAX_HEIGHT)
            raise ValidationError(m)
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
###############################################################################
#
# ODOO (ex OpenERP)
# Open Source Management Solution
# Copyright (C) 2001-2015 Micronaet S.r.l. (<https://micronaet.com>)
# Developer: Nicola Riolini @thebrush (<https://it.linkedin.com/in/thebrush>)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################

import os
import pdb
import sys
import logging
import openerp
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID
from openerp import tools
from openerp.tools.translate import _
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class ProductBomReportLimitWizard(orm.TransientModel):
    """ Wizard for open report with limited price date
    """
    _name = 'product.bom.report.limit.wizard'

    # --------------------
    # Wizard button event:
    # --------------------
    def action_print_invoice_cost_analysis(self, cr, uid, ids, context=None):
        """ Compare price with extra period
        """
        product_pool = self.pool.get('product.product')
        line_pool = self.pool.get('account.invoice.line')
        excel_pool = self.pool.get('excel.writer')

        # ---------------------------------------------------------------------
        #                          Generate data:
        # ---------------------------------------------------------------------
        if context is None:
            context = {}
        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]

        # ---------------------------------------------------------------------
        # Setup domain for invoice:
        # ---------------------------------------------------------------------
        domain = []
        from_date = wiz_proxy.from_date
        to_date = wiz_proxy.to_date
        if from_date:
            domain.append(('invoice_id.date_invoice', '>=', from_date))
        if to_date:
            domain.append(('invoice_id.date_invoice', '<=', to_date))

        # ---------------------------------------------------------------------
        # Load DB template
        # ---------------------------------------------------------------------
        product_ids = product_pool.search(cr, uid, [
            ('bom_selection', '=', True),
        ], context=context)
        bom_data = {}
        for product in product_pool.browse(
                cr, uid, product_ids, context=context):
            code5 = (product.default_code or '')[:5]
            if not code5:
                _logger.error('Prodotto senza codice: %s' % product.name)
                continue
            bom_data[code5] = product

        # ---------------------------------------------------------------------
        #                          Excel export:
        # ---------------------------------------------------------------------
        ws_name = 'Distinte'

        header = [
            'Stagione', 'Cliente', 'Fattura', 'Data',
            'Prodotto', 'Nome', 'DB',
            'Quant.', 'Prezzo', 'Netto', 'Costo', 'Margine',
            'No DB', 'Errore',
        ]
        width = [
            8, 35, 12, 10,
            15, 30, 8,
            10, 10, 10, 10, 10,
            5, 40,
        ]

        # ---------------------------------------------------------------------
        # Create WS:
        # ---------------------------------------------------------------------
        excel_pool.create_worksheet(name=ws_name)
        excel_pool.column_width(ws_name, width)
        # excel_pool.row_height(ws_name, row_list, height=10)
        title = ['Controllo margini fatturato']

        # ---------------------------------------------------------------------
        # Generate format used:
        # ---------------------------------------------------------------------
        excel_pool.set_format(number_format='#,##0.#0')
        excel_format = {
            'title': excel_pool.get_format(key='title'),
            'header': excel_pool.get_format(key='header'),
            'white': {
                'text': excel_pool.get_format(key='text'),
                'number': excel_pool.get_format(key='number'),
            },
            'yellow': {
                'text': excel_pool.get_format(key='bg_yellow'),
                'number': excel_pool.get_format(key='bg_yellow_number'),
            },
            'red': {
                'text': excel_pool.get_format(key='bg_red'),
                'number': excel_pool.get_format(key='bg_red_number'),
            },
            'green': {
                'text': excel_pool.get_format(key='bg_green'),
                'number': excel_pool.get_format(key='bg_green_number'),
            },
        }

        # ---------------------------------------------------------------------
        # Write title / header
        # ---------------------------------------------------------------------
        row = 0
        excel_pool.write_xls_line(
            ws_name, row, [title], default_format=excel_format['title'])
        excel_pool.freeze_panes(ws_name, 2, 5)

        row += 1
        excel_pool.write_xls_line(
            ws_name, row, header, default_format=excel_format['header'])
        excel_pool.autofilter(ws_name, row, 0, row, len(header) - 1)

        line_ids = line_pool.search(cr, uid, domain, context=context)
        for line in line_pool.browse(cr, uid, line_ids, context=context):
            # -----------------------------------------------------------------
            # Read data:
            # -----------------------------------------------------------------
            invoice = line.invoice_id
            partner = invoice.partner_id
            product = line.product_id
            code5 = (product.default_code or '')[:5]
            quantity = line.quantity

            # -----------------------------------------------------------------
            # Calc data used:
            # -----------------------------------------------------------------
            if quantity:
                real_price = line.price_subtotal / quantity
            else:
                real_price = 0.0

            # Bom price
            bom_product = bom_data.get(code5)
            if bom_product:
                cost = bom_product.to_industrial
                margin = real_price - cost
                db = code5
                error = ''
            else:
                cost = 0.0
                margin = 0.0  # no value if no cost!
                db = ''
                error = 'DB non trovata (niente margine)'

            # -----------------------------------------------------------------
            # Color setup:
            # -----------------------------------------------------------------
            if real_price < 0:
                color = excel_format['red']
            elif not margin:
                color = excel_format['yellow']
            else:
                color = excel_format['white']

            # -----------------------------------------------------------------
            # Write data:
            # -----------------------------------------------------------------
            data = [
                line.season_period,
                partner.name,
                invoice.number,
                invoice.date_invoice,

                product.default_code,
                product.name,
                db,

                quantity,
                (line.price_unit, color['number']),
                (real_price, color['number']),
                (cost, color['number']),

                (margin, color['number']),
                '' if db else 'X',
                error,
            ]
            row += 1
            excel_pool.write_xls_line(
                ws_name, row, data, default_format=color['text'])

        return excel_pool.return_attachment(cr, uid, 'Comparativo fatturato')

    def action_print_extra_period(self, cr, uid, ids, context=None):
        """ Compare price with extra period
        """
        product_pool = self.pool.get('product.product')
        excel_pool = self.pool.get('excel.writer')

        # ---------------------------------------------------------------------
        #                          Generate data:
        # ---------------------------------------------------------------------
        if context is None:
            context = {}

        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]
        master_data = {}
        from_date = '1975-01-01'
        references = ['']
        for reference in wiz_proxy.extra_period.split(';'):
            reference = reference.strip()
            to_date = '%s-%s-%s' % (
                reference[-4:],
                reference[3:5],
                reference[:2],
            )
            references.append(to_date)
        references.sort()
        _logger.warning('Multi report for date: %s' % (references, ))

        # First reference normal report!
        for reference in references:
            if reference:
                datas = {
                    'wizard': True,
                    'from_date': from_date,
                    'to_date': reference,
                }
            else:
                datas = {
                    'wizard': True,
                }
            records = product_pool.report_get_objects_bom_industrial_cost(
                    cr, uid, datas=datas, context=context)

            for record in records:
                # Explode record:
                (min_price, max_price, error, components, extra1, extra2,
                 index, total, product, parameter, total_text,
                 pipe_total_weight, simulated_price) = record

                # Write all price present (False = reference for 100%)
                # todo manage error field?
                if product not in master_data:
                        master_data[product] = ({}, simulated_price)
                master_data[product][0][reference] = max_price  # Save this

        # ---------------------------------------------------------------------
        #                          Excel export:
        # ---------------------------------------------------------------------
        ws_name = 'Distinte'
        header = [
            'Codice',
            'Descrizione',
            'Prezzo riferimento',

            'Prezzo simulato',
            'Variaz. %',
        ]
        width = [
            20, 40, 15,
            15, 10,
        ]
        for reference in references[1:]:
            header.append('Al %s' % reference)
            header.append('Diff. %')
            width.append(15)
            width.append(10)

        # ---------------------------------------------------------------------
        # Create WS:
        # ---------------------------------------------------------------------
        excel_pool.create_worksheet(name=ws_name)
        excel_pool.column_width(ws_name, width)
        # excel_pool.row_height(ws_name, row_list, height=10)
        title = ('Confronto distinte base',)

        # ---------------------------------------------------------------------
        # Generate format used:
        # ---------------------------------------------------------------------
        excel_pool.set_format()
        f_title = excel_pool.get_format(key='title')
        f_header = excel_pool.get_format(key='header')
        f_text = excel_pool.get_format(key='text')
        f_number = excel_pool.get_format(key='number')

        # ---------------------------------------------------------------------
        # Write title / header
        # ---------------------------------------------------------------------
        row = 0
        excel_pool.write_xls_line(
            ws_name, row, [title], default_format=f_title)

        row += 1
        excel_pool.write_xls_line(
            ws_name, row, header, default_format=f_header)

        # ---------------------------------------------------------------------
        # Product selection:
        # ---------------------------------------------------------------------
        for product in sorted(master_data, key=lambda x: x.default_code):
            row += 1
            prices, simulated_price = master_data[product]
            default_code = product.default_code or ''
            current_price = prices['']
            if current_price:
                simulated_rate = \
                    (simulated_price - current_price) / current_price * 100.0
            else:
                simulated_rate = '/'
            line = [
                default_code or '',
                u'%s' % product.name,
                (current_price, f_number),
                (simulated_price, f_number),
                (simulated_rate, f_number),
            ]

            # Append other record data
            for reference in references[1:]:
                this_price = prices.get(reference, 0.0)
                line.append(this_price)
                if current_price:
                    this_rate = \
                        (this_price - current_price) / current_price * 100.0
                else:
                    this_rate = 0.0
                # Calc rate difference
                line.append(this_rate)
            excel_pool.write_xls_line(
                ws_name, row, line, default_format=f_text)
        return excel_pool.return_attachment(cr, uid, 'Distinte base')

    def action_print(self, cr, uid, ids, context=None):
        """ Event for print report
        """
        if context is None:
            context = {}

        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]
        from_date = wiz_proxy.from_date or False
        to_date = wiz_proxy.to_date or False
        report_name = wiz_proxy.report_name
        if not to_date or not from_date:
            raise osv.except_osv(
                _('Errore report'),
                _('Il range di date è obbligatorio'),
                )
        datas = {
            'wizard': True,
            'from_date': from_date,
            'to_date': to_date,
            }

        return {
            'type': 'ir.actions.report.xml',
            'report_name': report_name,
            'datas': datas,
            }

    _columns = {
        'from_date': fields.date('From date'),
        'to_date': fields.date('To date'),
        'report_name': fields.selection([
            ('industrial_cost_bom_report', 'Con costi'),
            ('industrial_cost_bom_no_price_report', 'Senza costi'),
        ], 'Tipo report', required=True),
        'extra_period': fields.char(
            'Date valutazione',
            help='Periodi extra l\'attuale, es. per avere gli ultrimi 3 anni:'
                 '01/09/2020;01/09/2019;01/09/2018'),
        }

    _defaults = {
        'report_name': lambda *x: 'industrial_cost_bom_report',
    }
<commit_msg>generic bugfix (fast message)<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
###############################################################################
#
# ODOO (ex OpenERP)
# Open Source Management Solution
# Copyright (C) 2001-2015 Micronaet S.r.l. (<https://micronaet.com>)
# Developer: Nicola Riolini @thebrush (<https://it.linkedin.com/in/thebrush>)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################

import os
import pdb
import sys
import logging
import openerp
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID
from openerp import tools
from openerp.tools.translate import _
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class ProductBomReportLimitWizard(orm.TransientModel):
    """ Wizard for open report with limited price date
    """
    _name = 'product.bom.report.limit.wizard'

    # --------------------
    # Wizard button event:
    # --------------------
    def action_print_invoice_cost_analysis(self, cr, uid, ids, context=None):
        """ Compare price with extra period
        """
        product_pool = self.pool.get('product.product')
        line_pool = self.pool.get('account.invoice.line')
        excel_pool = self.pool.get('excel.writer')

        # ---------------------------------------------------------------------
        #                          Generate data:
        # ---------------------------------------------------------------------
        if context is None:
            context = {}
        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]

        # ---------------------------------------------------------------------
        # Setup domain for invoice:
        # ---------------------------------------------------------------------
        domain = []
        from_date = wiz_proxy.from_date
        to_date = wiz_proxy.to_date
        if from_date:
            domain.append(('invoice_id.date_invoice', '>=', from_date))
        if to_date:
            domain.append(('invoice_id.date_invoice', '<=', to_date))

        # ---------------------------------------------------------------------
        # Load DB template
        # ---------------------------------------------------------------------
        product_ids = product_pool.search(cr, uid, [
            ('bom_selection', '=', True),
        ], context=context)
        bom_data = {}
        for product in product_pool.browse(
                cr, uid, product_ids, context=context):
            code5 = (product.default_code or '')[:5]
            if not code5:
                _logger.error('Prodotto senza codice: %s' % product.name)
                continue
            bom_data[code5] = product

        # ---------------------------------------------------------------------
        #                          Excel export:
        # ---------------------------------------------------------------------
        ws_name = 'Distinte'

        header = [
            'Stagione', 'Cliente', 'Fattura', 'Data',
            'Prodotto', 'Nome', 'DB',
            'Quant.', 'Pr. unit', 'Pr. Netto', 'Costo DB', 'Marg. unit.',
            'Fatt. tot.', 'Marg. tot',
            'No DB', 'Errore',
        ]
        width = [
            8, 35, 12, 10,
            15, 30, 8,
            10, 10, 10, 10, 10,
            10, 10,
            5, 40,
        ]

        # ---------------------------------------------------------------------
        # Create WS:
        # ---------------------------------------------------------------------
        excel_pool.create_worksheet(name=ws_name)
        excel_pool.column_width(ws_name, width)
        # excel_pool.row_height(ws_name, row_list, height=10)
        title = ['Controllo margini fatturato']

        # ---------------------------------------------------------------------
        # Generate format used:
        # ---------------------------------------------------------------------
        excel_pool.set_format(number_format='#,##0.#0')
        excel_format = {
            'title': excel_pool.get_format(key='title'),
            'header': excel_pool.get_format(key='header'),
            'white': {
                'text': excel_pool.get_format(key='text'),
                'number': excel_pool.get_format(key='number'),
            },
            'yellow': {
                'text': excel_pool.get_format(key='bg_yellow'),
                'number': excel_pool.get_format(key='bg_yellow_number'),
            },
            'red': {
                'text': excel_pool.get_format(key='bg_red'),
                'number': excel_pool.get_format(key='bg_red_number'),
            },
            'green': {
                'text': excel_pool.get_format(key='bg_green'),
                'number': excel_pool.get_format(key='bg_green_number'),
            },
        }

        # ---------------------------------------------------------------------
        # Write title / header
        # ---------------------------------------------------------------------
        row = 0
        excel_pool.write_xls_line(
            ws_name, row, [title], default_format=excel_format['title'])
        excel_pool.freeze_panes(ws_name, 2, 5)

        row += 1
        excel_pool.write_xls_line(
            ws_name, row, header, default_format=excel_format['header'])
        excel_pool.autofilter(ws_name, row, 0, row, len(header) - 1)

        line_ids = line_pool.search(cr, uid, domain, context=context)
        for line in line_pool.browse(cr, uid, line_ids, context=context):
            # -----------------------------------------------------------------
            # Read data:
            # -----------------------------------------------------------------
            invoice = line.invoice_id
            partner = invoice.partner_id
            product = line.product_id
            code5 = (product.default_code or '')[:5]
            quantity = line.quantity

            # -----------------------------------------------------------------
            # Calc data used:
            # -----------------------------------------------------------------
            subtotal = line.price_subtotal
            if quantity:
                real_price = subtotal / quantity
            else:
                real_price = 0.0

            # Bom price
            bom_product = bom_data.get(code5)
            if bom_product:
                cost = bom_product.to_industrial
                margin = real_price - cost
                margin_total = margin * quantity
                db = code5
                error = ''
            else:
                cost = margin = margin_total = 0.0  # no value if no cost!
                db = ''
                error = 'DB non trovata (niente margine)'

            # -----------------------------------------------------------------
            # Color setup:
            # -----------------------------------------------------------------
            if real_price < 0:
                color = excel_format['red']
            elif not margin:
                color = excel_format['yellow']
            else:
                color = excel_format['white']

            # -----------------------------------------------------------------
            # Write data:
            # -----------------------------------------------------------------
            data = [
                line.season_period,
                partner.name,
                invoice.number,
                invoice.date_invoice,

                product.default_code,
                product.name,
                db,

                quantity,
                (line.price_unit, color['number']),
                (real_price, color['number']),
                (cost, color['number']),
                (margin, color['number']),

                (subtotal, color['number']),
                (margin_total, color['number']),

                '' if db else 'X',
                error,
            ]
            row += 1
            excel_pool.write_xls_line(
                ws_name, row, data, default_format=color['text'])

        return excel_pool.return_attachment(cr, uid, 'Comparativo fatturato')

    def action_print_extra_period(self, cr, uid, ids, context=None):
        """ Compare price with extra period
        """
        product_pool = self.pool.get('product.product')
        excel_pool = self.pool.get('excel.writer')

        # ---------------------------------------------------------------------
        #                          Generate data:
        # ---------------------------------------------------------------------
        if context is None:
            context = {}

        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]
        master_data = {}
        from_date = '1975-01-01'
        references = ['']
        for reference in wiz_proxy.extra_period.split(';'):
            reference = reference.strip()
            to_date = '%s-%s-%s' % (
                reference[-4:],
                reference[3:5],
                reference[:2],
            )
            references.append(to_date)
        references.sort()
        _logger.warning('Multi report for date: %s' % (references, ))

        # First reference normal report!
        for reference in references:
            if reference:
                datas = {
                    'wizard': True,
                    'from_date': from_date,
                    'to_date': reference,
                }
            else:
                datas = {
                    'wizard': True,
                }
            records = product_pool.report_get_objects_bom_industrial_cost(
                    cr, uid, datas=datas, context=context)

            for record in records:
                # Explode record:
                (min_price, max_price, error, components, extra1, extra2,
                 index, total, product, parameter, total_text,
                 pipe_total_weight, simulated_price) = record

                # Write all price present (False = reference for 100%)
                # todo manage error field?
                if product not in master_data:
                        master_data[product] = ({}, simulated_price)
                master_data[product][0][reference] = max_price  # Save this

        # ---------------------------------------------------------------------
        #                          Excel export:
        # ---------------------------------------------------------------------
        ws_name = 'Distinte'
        header = [
            'Codice',
            'Descrizione',
            'Prezzo riferimento',

            'Prezzo simulato',
            'Variaz. %',
        ]
        width = [
            20, 40, 15,
            15, 10,
        ]
        for reference in references[1:]:
            header.append('Al %s' % reference)
            header.append('Diff. %')
            width.append(15)
            width.append(10)

        # ---------------------------------------------------------------------
        # Create WS:
        # ---------------------------------------------------------------------
        excel_pool.create_worksheet(name=ws_name)
        excel_pool.column_width(ws_name, width)
        # excel_pool.row_height(ws_name, row_list, height=10)
        title = ('Confronto distinte base',)

        # ---------------------------------------------------------------------
        # Generate format used:
        # ---------------------------------------------------------------------
        excel_pool.set_format()
        f_title = excel_pool.get_format(key='title')
        f_header = excel_pool.get_format(key='header')
        f_text = excel_pool.get_format(key='text')
        f_number = excel_pool.get_format(key='number')

        # ---------------------------------------------------------------------
        # Write title / header
        # ---------------------------------------------------------------------
        row = 0
        excel_pool.write_xls_line(
            ws_name, row, [title], default_format=f_title)

        row += 1
        excel_pool.write_xls_line(
            ws_name, row, header, default_format=f_header)

        # ---------------------------------------------------------------------
        # Product selection:
        # ---------------------------------------------------------------------
        for product in sorted(master_data, key=lambda x: x.default_code):
            row += 1
            prices, simulated_price = master_data[product]
            default_code = product.default_code or ''
            current_price = prices['']
            if current_price:
                simulated_rate = \
                    (simulated_price - current_price) / current_price * 100.0
            else:
                simulated_rate = '/'
            line = [
                default_code or '',
                u'%s' % product.name,
                (current_price, f_number),
                (simulated_price, f_number),
                (simulated_rate, f_number),
            ]

            # Append other record data
            for reference in references[1:]:
                this_price = prices.get(reference, 0.0)
                line.append(this_price)
                if current_price:
                    this_rate = \
                        (this_price - current_price) / current_price * 100.0
                else:
                    this_rate = 0.0
                # Calc rate difference
                line.append(this_rate)
            excel_pool.write_xls_line(
                ws_name, row, line, default_format=f_text)
        return excel_pool.return_attachment(cr, uid, 'Distinte base')

    def action_print(self, cr, uid, ids, context=None):
        """ Event for print report
        """
        if context is None:
            context = {}

        wiz_proxy = self.browse(cr, uid, ids, context=context)[0]
        from_date = wiz_proxy.from_date or False
        to_date = wiz_proxy.to_date or False
        report_name = wiz_proxy.report_name
        if not to_date or not from_date:
            raise osv.except_osv(
                _('Errore report'),
                _('Il range di date è obbligatorio'),
                )
        datas = {
            'wizard': True,
            'from_date': from_date,
            'to_date': to_date,
            }

        return {
            'type': 'ir.actions.report.xml',
            'report_name': report_name,
            'datas': datas,
            }

    _columns = {
        'from_date': fields.date('From date'),
        'to_date': fields.date('To date'),
        'report_name': fields.selection([
            ('industrial_cost_bom_report', 'Con costi'),
            ('industrial_cost_bom_no_price_report', 'Senza costi'),
        ], 'Tipo report', required=True),
        'extra_period': fields.char(
            'Date valutazione',
            help='Periodi extra l\'attuale, es. per avere gli ultrimi 3 anni:'
                 '01/09/2020;01/09/2019;01/09/2018'),
        }

    _defaults = {
        'report_name': lambda *x: 'industrial_cost_bom_report',
    }
<|endoftext|>


<commit_before># Frequency Finder
# https://www.nostarch.com/crackingcodes/ (BSD Licensed)

ETAOIN = 'ETAOINSHRDLCUMWFGYPBVKJXQZ'
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def getLetterCount(message):
    # Returns a dictionary with keys of single letters and values of the
    # count of how many times they appear in the message parameter:
    letterCount = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0, 'F': 0,
                   'G': 0, 'H': 0, 'I': 0, 'J': 0, 'K': 0, 'L': 0, 'M': 0, 'N': 0,
                   'O': 0, 'P': 0, 'Q': 0, 'R': 0, 'S': 0, 'T': 0, 'U': 0, 'V': 0,
                   'W': 0, 'X': 0, 'Y': 0, 'Z': 0}

    for letter in message.upper():
        if letter in LETTERS:
            letterCount[letter] += 1

    return letterCount

def getItemAtIndexZero(items):
    return items[0]

def getFrequencyOrder(message):
    # Returns a string of the alphabet letters arranged in order of most
    # frequently occurring in the message parameter.

    # First, get a dictionary of each letter and its frequency count:
    letterToFreq = getLetterCount(message)

    # Second, make a dictionary of each frequency count to the letter(s)
    # with that frequency:
    freqToLetter = {}
    for letter in LETTERS:
        if letterToFreq[letter] not in freqToLetter:
            freqToLetter[letterToFreq[letter]] = [letter]
        else:
            freqToLetter[letterToFreq[letter]].append(letter)

    # Third, put each list of letters in reverse "ETAOIN" order, and then
    # convert it to a string:
    for freq in freqToLetter:
        freqToLetter[freq].sort(key=ETAOIN.find, reverse=True)
        freqToLetter[freq] = ''.join(freqToLetter[freq])

    # Fourth, convert the freqToLetter dictionary to a list of
    # tuple pairs (key, value), and then sort them:
    freqPairs = list(freqToLetter.items())
    freqPairs.sort(key=getItemAtIndexZero, reverse=True)

    # Fifth, now that the letters are ordered by frequency, extract all
    # the letters for the final string:
    freqOrder = []
    for freqPair in freqPairs:
        freqOrder.append(freqPair[1])

    return ''.join(freqOrder)

def englishFreqMatchScore(message):
    # Return the number of matches that the string in the message
    # parameter has when its letter frequency is compared to English
    # letter frequency. A "match" is how many of its six most frequent
    # and six least frequent letters are among the six most frequent and
    # six least frequent letters for English.
    freqOrder = getFrequencyOrder(message)

    matchScore = 0
    # Find how many matches for the six most common letters there are:
    for commonLetter in ETAOIN[:6]:
        if commonLetter in freqOrder[:6]:
            matchScore += 1
    # Find how many matches for the six least common letters there are:
    for uncommonLetter in ETAOIN[-6:]:
        if uncommonLetter in freqOrder[-6:]:
            matchScore += 1

    return matchScore<commit_msg>Update freqAnalysis: fixed PEP8 spacing<commit_after># Frequency Finder
# https://www.nostarch.com/crackingcodes/ (BSD Licensed)

ETAOIN = 'ETAOINSHRDLCUMWFGYPBVKJXQZ'
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def getLetterCount(message):
    # Returns a dictionary with keys of single letters and values of the
    # count of how many times they appear in the message parameter:
    letterCount = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0, 'F': 0,
                   'G': 0, 'H': 0, 'I': 0, 'J': 0, 'K': 0, 'L': 0, 'M': 0, 'N': 0,
                   'O': 0, 'P': 0, 'Q': 0, 'R': 0, 'S': 0, 'T': 0, 'U': 0, 'V': 0,
                   'W': 0, 'X': 0, 'Y': 0, 'Z': 0}

    for letter in message.upper():
        if letter in LETTERS:
            letterCount[letter] += 1

    return letterCount

def getItemAtIndexZero(items):
    return items[0]

def getFrequencyOrder(message):
    # Returns a string of the alphabet letters arranged in order of most
    # frequently occurring in the message parameter.

    # First, get a dictionary of each letter and its frequency count:
    letterToFreq = getLetterCount(message)

    # Second, make a dictionary of each frequency count to the letter(s)
    # with that frequency:
    freqToLetter = {}
    for letter in LETTERS:
        if letterToFreq[letter] not in freqToLetter:
            freqToLetter[letterToFreq[letter]] = [letter]
        else:
            freqToLetter[letterToFreq[letter]].append(letter)

    # Third, put each list of letters in reverse "ETAOIN" order, and then
    # convert it to a string:
    for freq in freqToLetter:
        freqToLetter[freq].sort(key=ETAOIN.find, reverse=True)
        freqToLetter[freq] = ''.join(freqToLetter[freq])

    # Fourth, convert the freqToLetter dictionary to a list of
    # tuple pairs (key, value), and then sort them:
    freqPairs = list(freqToLetter.items())
    freqPairs.sort(key=getItemAtIndexZero, reverse=True)

    # Fifth, now that the letters are ordered by frequency, extract all
    # the letters for the final string:
    freqOrder = []
    for freqPair in freqPairs:
        freqOrder.append(freqPair[1])

    return ''.join(freqOrder)

def englishFreqMatchScore(message):
    # Return the number of matches that the string in the message
    # parameter has when its letter frequency is compared to English
    # letter frequency. A "match" is how many of its six most frequent
    # and six least frequent letters are among the six most frequent and
    # six least frequent letters for English.
    freqOrder = getFrequencyOrder(message)

    matchScore = 0
    # Find how many matches for the six most common letters there are:
    for commonLetter in ETAOIN[:6]:
        if commonLetter in freqOrder[:6]:
            matchScore += 1
    # Find how many matches for the six least common letters there are:
    for uncommonLetter in ETAOIN[-6:]:
        if uncommonLetter in freqOrder[-6:]:
            matchScore += 1

    return matchScore
<|endoftext|>


<commit_before>from __future__ import print_function, unicode_literals

from asyncio import get_event_loop, Protocol, sleep, coroutine, Future

# Should this inherit from both asyncio.protocol and HTTPConnection? (Probably not, but might be OK)

class HTTPConnection(Protocol):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self._loop = get_event_loop()
        self._conn = None

    def connect(self):
        self._conn = self._loop.create_connection(lambda: self, self.host, self.port)
        self._loop.run_until_complete(self._conn)

    def close(self):
        pass
        #self._conn.close()

#    @coroutine
#    def driver(self):
#        while not self._eof_received:
#            print("Waiting...")
#            yield from sleep(1)
#        print("Done")

    def request(self, method, url, body=None, headers={}, callback=None):
        if method == "POST":
            headers["Expect"] = "100-continue"
#            headers["Content-Length"] = str(len(body))
            headers["Transfer-Encoding"] = "chunked"
        self._ready_to_send_body, self._eof_received = False, False
        self.body = body
        self.response = b""
        self.transport.write("{} {} HTTP/1.1\r\n".format(method, url).encode())
        for header in headers:
            self.transport.write("{}:{}\r\n".format(header, headers[header]).encode())
        self.transport.write(b"\r\n")
        self._ready_to_send_body = Future()
        self._loop.run_until_complete(self._ready_to_send_body)
        self._loop.run_until_complete(self._send_body())
        self._done = Future()
        if callback is None:
            self._loop.run_until_complete(self._done)
            return self.response
        else:
            pass

    def getresponse(self):
        pass

    def __del__(self):
        self.close()

    def connection_made(self, transport):
        self.transport = transport
        print("Connection made:", transport)

    def connection_lost(self, exc):
        print('server closed the connection')
        #asyncio.get_event_loop().stop()

    def eof_received(self):
        print("Received EOF")
        self._done.set_result(None)
#        self._eof_received = True

    def pause_writing(self):
        print("Received pause writing cb")

    def resume_writing(self):
        print("Received resume writing cb")

    def data_received(self, data):
        print("Received data:", data)
        # TODO: fix this up to not be stupid
        if data.startswith(b"HTTP/1.1 100 Continue"):
            print("Got 100 continue, ready to send body")
            self._ready_to_send_body.set_result(None)
        self.response += data

    @coroutine
    def _send_body(self):
        print("Will send body")
        from io import BytesIO
        b = BytesIO(self.body)
        cs = 1024
        while True:
            c = b.read(cs)
            if c == b"":
                break
            yield from sleep(0.1)
            yield from self._send_chunk(c)

        self.transport.write(b"0\r\n\r\n")
        print("Done writing body")

    @coroutine
    def _send_chunk(self, chunk):
        self.transport.write(bytes("{:x}\r\n".format(len(chunk)), encoding="utf-8"))
        self.transport.write(chunk)
        self.transport.write(b"\r\n")
        print("Wrote", len(chunk), "bytes")

c = HTTPConnection("localhost", 9000)
c.connect()
response = c.request("POST", "/", headers={"foo": "bar", "wat": "wat"}, body=b"0123456789ABCDEF"*1024)
print("Got response:", response)

class HTTPResponse(object):
    def __iter__(self):
        # Chunked response iterator
        pass

    def __enter__(self):
        pass
    def __exit__(self):
        pass

    def read(self, amt=None):
        pass
    def readinto(self, b):
        pass
<commit_msg>Update __init__.py<commit_after>from __future__ import print_function, unicode_literals

from asyncio import get_event_loop, Protocol, sleep, coroutine, Future

# Should this inherit from both asyncio.protocol and HTTPConnection? (Probably not, but might be OK)

class HTTPConnection(Protocol):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self._loop = get_event_loop()
        self._conn = None

    def connect(self):
        self._conn = self._loop.create_connection(lambda: self, self.host, self.port)
        self._loop.run_until_complete(self._conn)

    def close(self):
        pass
        #self._conn.close()

    def request(self, method, url, body=None, headers={}, callback=None):
        if method == "POST":
            headers["Expect"] = "100-continue"
#            headers["Content-Length"] = str(len(body))
            headers["Transfer-Encoding"] = "chunked"
        self._ready_to_send_body, self._eof_received = False, False
        self.body = body
        self.response = b""
        self.transport.write("{} {} HTTP/1.1\r\n".format(method, url).encode())
        for header in headers:
            self.transport.write("{}:{}\r\n".format(header, headers[header]).encode())
        self.transport.write(b"\r\n")
        self._ready_to_send_body = Future()
        self._loop.run_until_complete(self._ready_to_send_body)
        self._loop.run_until_complete(self._send_body())
        self._done = Future()
        if callback is None:
            self._loop.run_until_complete(self._done)
            return self.response
        else:
            pass

    def getresponse(self):
        pass

    def __del__(self):
        self.close()

    def connection_made(self, transport):
        self.transport = transport
        print("Connection made:", transport)

    def connection_lost(self, exc):
        print('server closed the connection')
        #asyncio.get_event_loop().stop()

    def eof_received(self):
        print("Received EOF")
        self._done.set_result(None)
#        self._eof_received = True

    def pause_writing(self):
        print("Received pause writing cb")

    def resume_writing(self):
        print("Received resume writing cb")

    def data_received(self, data):
        print("Received data:", data)
        # TODO: fix this up to not be stupid
        if data.startswith(b"HTTP/1.1 100 Continue"):
            print("Got 100 continue, ready to send body")
            self._ready_to_send_body.set_result(None)
        self.response += data

    @coroutine
    def _send_body(self):
        print("Will send body")
        from io import BytesIO
        b = BytesIO(self.body)
        cs = 1024
        while True:
            c = b.read(cs)
            if c == b"":
                break
            yield from sleep(0.1)
            yield from self._send_chunk(c)

        self.transport.write(b"0\r\n\r\n")
        print("Done writing body")

    @coroutine
    def _send_chunk(self, chunk):
        self.transport.write(bytes("{:x}\r\n".format(len(chunk)), encoding="utf-8"))
        self.transport.write(chunk)
        self.transport.write(b"\r\n")
        print("Wrote", len(chunk), "bytes")

c = HTTPConnection("localhost", 9000)
c.connect()
response = c.request("POST", "/", headers={"foo": "bar", "wat": "wat"}, body=b"0123456789ABCDEF"*1024)
print("Got response:", response)

class HTTPResponse(object):
    def __iter__(self):
        # Chunked response iterator
        pass

    def __enter__(self):
        pass
    def __exit__(self):
        pass

    def read(self, amt=None):
        pass
    def readinto(self, b):
        pass
<|endoftext|>