"""
Legend classes to use with `QGraphicsScene` objects.
"""
import numpy as np
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt

class Anchorable(QtGui.QGraphicsWidget):

    __corners = ['topLeft', 'topRight', 'bottomLeft', 'bottomRight']
    TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT = __corners

    def __init__(self, parent=None, corner='bottomRight', offset=(10, 10)):
        super().__init__(parent)

        self.__corner_str = corner if corner in self.__corners else None
        # The flag indicates whether or not the item has been drawn on yet.
        # This is useful for determining the initial offset, due to the fact
        # that dimensions are available in the resize event, which can occur
        # multiple times.
        self.__has_been_drawn = False

        if isinstance(offset, tuple) or isinstance(offset, list):
            assert len(offset) == 2
            self.__offset = QtCore.QPoint(*offset)
        elif isinstance(offset, QtCore.QPoint):
            self.__offset = offset

    def moveEvent(self, ev):
        super().moveEvent(ev)
        # This check is needed because simply resizing the window will cause
        # the item to move and trigger a `moveEvent` therefore we need to check
        # that the movement was done intentionally by the user using the mouse
        if QtGui.QApplication.mouseButtons() == Qt.LeftButton:
            self.recalculate_offset()

    def resizeEvent(self, ev):
        # When the item is first shown, we need to update its position
        super().resizeEvent(ev)
        if not self.__has_been_drawn:
            self.__offset = self.__calculate_actual_offset(self.__offset)
            self.update_pos()
            self.__has_been_drawn = True

    def showEvent(self, ev):
        # When the item is first shown, we need to update its position
        super().showEvent(ev)
        self.update_pos()

    def recalculate_offset(self):
        # This is called whenever the item is being moved and needs to
        # recalculate its offset
        view = self.__get_view()
        # Get the view box and position of legend relative to the view,
        # not the scene
        pos = view.mapFromScene(self.pos())
        view_box = self.__usable_viewbox()

        self.__corner_str = self.__get_closest_corner()
        viewbox_corner = getattr(view_box, self.__corner_str)()

        self.__offset = viewbox_corner - pos

    def update_pos(self):
        # This is called whenever something happened with the view that caused
        # this item to move from its anchored position, so we have to adjust
        # the position to maintain the effect of being anchored
        view = self.__get_view()
        if self.__corner_str and view is not None:
            box = self.__usable_viewbox()
            corner = getattr(box, self.__corner_str)()
            new_pos = corner - self.__offset
            self.setPos(view.mapToScene(new_pos))

    def __calculate_actual_offset(self, offset):
        """Take the offset specified in the constructor and calculate the
        actual offset from the top left corner of the item so positioning can
        be done correctly."""
        off_x, off_y = offset.x(), offset.y()
        w, h = self.boundingRect().width(), self.boundingRect().height()
        if self.__corner_str == self.TOP_LEFT:
            return QtCore.QPoint(-off_x, -off_y)
        elif self.__corner_str == self.TOP_RIGHT:
            return QtCore.QPoint(off_x + w, -off_y)
        elif self.__corner_str == self.BOTTOM_RIGHT:
            return QtCore.QPoint(off_x + w, off_y + h)
        elif self.__corner_str == self.BOTTOM_LEFT:
            return QtCore.QPoint(-off_x, off_y + h)

    def __get_closest_corner(self):
        view = self.__get_view()
        # Get the view box and position of legend relative to the view,
        # not the scene
        pos = view.mapFromScene(self.pos())
        legend_box = QtCore.QRect(pos, self.size().toSize())
        view_box = QtCore.QRect(QtCore.QPoint(0, 0), view.size())

        def distance(t1, t2):
            # 2d euclidean distance
            return np.sqrt((t1.x() - t2.x()) ** 2 + (t1.y() - t2.y()) ** 2)

        distances = [
            (distance(getattr(view_box, corner)(),
                      getattr(legend_box, corner)()), corner)
            for corner in self.__corners
        ]
        _, corner = min(distances)
        return corner

    def __get_own_corner(self):
        view = self.__get_view()
        pos = view.mapFromScene(self.pos())
        legend_box = QtCore.QRect(pos, self.size().toSize())
        return getattr(legend_box, self.__corner_str)()

    def __get_view(self):
        if self.scene() is not None:
            view, = self.scene().views()
            return view
        else:
            return None

    def __usable_viewbox(self):
        view = self.__get_view()

        if view.horizontalScrollBar().isVisible():
            h = view.horizontalScrollBar().size().height()
        else:
            h = 0

        if view.verticalScrollBar().isVisible():
            w = view.verticalScrollBar().size().width()
        else:
            w = 0

        size = view.size() - QtCore.QSize(w, h)
        return QtCore.QRect(QtCore.QPoint(0, 0), size)

class AnchorableGraphicsView(QtGui.QGraphicsView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.horizontalScrollBar().valueChanged.connect(
            self.update_anchored_items)
        self.verticalScrollBar().valueChanged.connect(
            self.update_anchored_items)

    def resizeEvent(self, ev):
        super().resizeEvent(ev)
        self.update_anchored_items()

    def mousePressEvent(self, ev):
        super().mousePressEvent(ev)
        self.update_anchored_items()

    def wheelEvent(self, ev):
        super().wheelEvent(ev)
        self.update_anchored_items()

    def mouseMoveEvent(self, ev):
        super().mouseMoveEvent(ev)
        self.update_anchored_items()

    def update_anchored_items(self):
        for item in self.__anchorable_items():
            item.update_pos()

    def __anchorable_items(self):
        return [i for i in self.scene().items() if isinstance(i, Anchorable)]

class ColorIndicator(QtGui.QGraphicsWidget):
    pass

class LegendItemSquare(ColorIndicator):
    """Legend square item.

    The legend square item is a small colored square image that can be plugged
    into the legend in front of the text object.

    This should only really be used in conjunction with ˙LegendItem˙.

    Parameters
    ----------
    color : QtGui.QColor
        The color of the square.
    parent : QtGui.QGraphicsItem

    See Also
    --------
    LegendItemCircle

    """

    SIZE = QtCore.QSizeF(12, 12)

    def __init__(self, color, parent):
        super().__init__(parent)

        height, width = self.SIZE.height(), self.SIZE.width()
        self.__square = QtGui.QGraphicsRectItem(0, 0, height, width)
        self.__square.setBrush(QtGui.QBrush(color))
        self.__square.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0)))
        self.__square.setParentItem(self)

    def sizeHint(self, size_hint, size_constraint=None, *args, **kwargs):
        return QtCore.QSizeF(self.__square.boundingRect().size())

class LegendItemCircle(ColorIndicator):
    """Legend circle item.

    The legend circle item is a small colored circle image that can be plugged
    into the legend in front of the text object.

    This should only really be used in conjunction with ˙LegendItem˙.

    Parameters
    ----------
    color : QtGui.QColor
        The color of the square.
    parent : QtGui.QGraphicsItem

    See Also
    --------
    LegendItemSquare

    """

    SIZE = QtCore.QSizeF(12, 12)

    def __init__(self, color, parent):
        super().__init__(parent)

        height, width = self.SIZE.height(), self.SIZE.width()
        self.__circle = QtGui.QGraphicsEllipseItem(0, 0, height, width)
        self.__circle.setBrush(QtGui.QBrush(color))
        self.__circle.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0)))
        self.__circle.setParentItem(self)

    def sizeHint(self, size_hint, size_constraint=None, *args, **kwargs):
        return QtCore.QSizeF(self.__circle.boundingRect().size())

class LegendItemTitle(QtGui.QGraphicsWidget):
    """Legend item title - the text displayed in the legend.

    This should only really be used in conjunction with ˙LegendItem˙.

    Parameters
    ----------
    text : str
    parent : QtGui.QGraphicsItem
    font : QtGui.QFont
        This

    """

    def __init__(self, text, parent, font):
        super().__init__(parent)

        self.__text = QtGui.QGraphicsTextItem(text.title())
        self.__text.setParentItem(self)
        self.__text.setFont(font)

    def sizeHint(self, size_hint, size_constraint=None, *args, **kwargs):
        return QtCore.QSizeF(self.__text.boundingRect().size())

class LegendItem(QtGui.QGraphicsLinearLayout):
    """Legend item - one entry in the legend.

    This represents one entry in the legend i.e. a color indicator and the text
    beside it.

    Parameters
    ----------
    color : QtGui.QColor
        The color that the entry will represent.
    title : str
        The text that will be displayed for the color.
    parent : QtGui.QGraphicsItem
    color_indicator_cls : ColorIndicator
        The type of `ColorIndicator` that will be used for the color.
    font : QtGui.QFont, optional

    """

    def __init__(self, color, title, parent, color_indicator_cls, font=None):
        super().__init__()

        self.__parent = parent
        self.__color_indicator = color_indicator_cls(color, parent)
        self.__title_label = LegendItemTitle(title, parent, font=font)

        self.addItem(self.__color_indicator)
        self.addItem(self.__title_label)

        # Make sure items are aligned properly, since the color box and text
        # won't be the same height.
        self.setAlignment(self.__color_indicator, Qt.AlignCenter)
        self.setAlignment(self.__title_label, Qt.AlignCenter)
        self.setContentsMargins(0, 0, 0, 0)
        self.setSpacing(5)

class LegendGradient(QtGui.QGraphicsWidget):
    """Gradient widget.

    A gradient square bar that can be used to display continuous values.

    Parameters
    ----------
    palette : iterable[QtGui.QColor]
    parent : QtGui.QGraphicsWidget
    orientation : Qt.Orientation

    Notes
    -----
    .. Note:: While the gradient does support any number of colors, any more
        than 3 is not very readable. This should not be a problem, since Orange
        only implements 2 or 3 colors.

    """

    # Default sizes (assume gradient is vertical by default)
    GRADIENT_WIDTH = 20
    GRADIENT_HEIGHT = 150

    def __init__(self, palette, parent, orientation):
        super().__init__(parent)

        self.__gradient = QtGui.QLinearGradient()
        num_colors = len(palette)
        for idx, stop in enumerate(palette):
            self.__gradient.setColorAt(idx * (1. / (num_colors - 1)), stop)

        # We need to tell the gradient where it's start and stop points are
        self.__gradient.setStart(QtCore.QPointF(0, 0))
        if orientation == Qt.Vertical:
            final_stop = QtCore.QPointF(0, self.GRADIENT_HEIGHT)
        else:
            final_stop = QtCore.QPointF(self.GRADIENT_HEIGHT, 0)
        self.__gradient.setFinalStop(final_stop)

        # Get the appropriate rectangle dimensions based on orientation
        if orientation == Qt.Vertical:
            w, h = self.GRADIENT_WIDTH, self.GRADIENT_HEIGHT
        elif orientation == Qt.Horizontal:
            w, h = self.GRADIENT_HEIGHT, self.GRADIENT_WIDTH

        self.__rect_item = QtGui.QGraphicsRectItem(0, 0, w, h, self)
        self.__rect_item.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0)))
        self.__rect_item.setBrush(QtGui.QBrush(self.__gradient))

    def sizeHint(self, size_hint, size_constraint=None, *args, **kwargs):
        return QtCore.QSizeF(self.__rect_item.boundingRect().size())

class ContinuousLegendItem(QtGui.QGraphicsLinearLayout):
    """Continuous legend item.

    Contains a gradient bar with the color ranges, as well as two labels - one
    on each side of the gradient bar.

    Parameters
    ----------
    palette : iterable[QtGui.QColor]
    values : iterable[float...]
        The number of values must match the number of colors in passed in the
        color palette.
    parent : QtGui.QGraphicsWidget
    font : QtGui.QFont
    orientation : Qt.Orientation

    """

    def __init__(self, palette, values, parent, font=None,
                 orientation=Qt.Vertical):
        if orientation == Qt.Vertical:
            super().__init__(Qt.Horizontal)
        else:
            super().__init__(Qt.Vertical)

        self.__parent = parent
        self.__palette = palette
        self.__values = values

        self.__gradient = LegendGradient(palette, parent, orientation)
        self.__labels_layout = QtGui.QGraphicsLinearLayout(orientation)

        str_vals = self._format_values(values)

        self.__start_label = LegendItemTitle(str_vals[0], parent, font=font)
        self.__end_label = LegendItemTitle(str_vals[1], parent, font=font)
        self.__labels_layout.addItem(self.__start_label)
        self.__labels_layout.addStretch(1)
        self.__labels_layout.addItem(self.__end_label)

        # Gradient should be to the left, then labels on the right if vertical
        if orientation == Qt.Vertical:
            self.addItem(self.__gradient)
            self.addItem(self.__labels_layout)
        # Gradient should be on the bottom, labels on top if horizontal
        elif orientation == Qt.Horizontal:
            self.addItem(self.__labels_layout)
            self.addItem(self.__gradient)

    @staticmethod
    def _format_values(values):
        """Get the formatted values to output."""
        return ['{:.3f}'.format(v) for v in values]

class LegendBuilder:
    """Legend builder.

    In most cases, the Orange.data.domain.Domain object will be available to
    you when displaying a dataset with a legend. This class makes the legend
    building process simpler, by parsing the domain and returing the
    appropriate legend type.

    Attributes
    ----------
    want_binned : bool, optional
        This only applies for continuous classes. Tell the builder if you want
        a binned (ranges of values e.g. 1-2, 2-3, 3-4) legend or if you want a
        smooth gradient legend. The default is False.

    Examples
    --------
    A basic example
    >>> legend = LegendBuilder()(domain, dataset)

    An example using the `want_binned` method
    >>> legend = LegendBuilder(want_binned=True)(domain, dataset)

    An example passing a kwarg to the `Legend` constructor.
    >>> legend = LegendBuilder()(
    >>>     domain,
    >>>     dataset,
    >>>     color_indicator_cls=LegendItemCircle)

    Notes
    -----
    .. note:: Note that even if some arguments are passed to the constructor,
        they may be ignored, based on the type of class variable the domain
        contains e.g. it would make no sense for the `want_binned` parameter to
        have any effect on discrete target classes.

    """

    def __init__(self, want_binned=False):
        self.want_binned = want_binned

    def __call__(self, domain, dataset, *args, **kwargs):
        """Build the appropriate legend instance.

        Parameters
        ----------
        domain : Orange.data.domain.Domain
        dataset : Orange.data.table.Table
            Note that no reference to the dataset is kept, it is only required
            to calculate some values that are then passed on to the Legend
            objects.
        args
            Any excess arguments will be passed down to the `Legend`
            constructor. See the `Legend` as well as it subclass constructors
            for a list of valid arguments.
        kwargs
            Any key word arguments will be passed down to the `Legend`
            constructor. See the `Legend` as well as it subclass constructors
            for a list of valid arguments.

        Returns
        -------
        Legend

        See Also
        --------
        Legend
        OWDiscreteLegend
        OWContinuousLegend
        OWBinnedContinuousLegend

        """
        if domain.class_var.is_discrete:
            return OWDiscreteLegend(*args, domain=domain, **kwargs)
        else:
            if self.want_binned:
                return OWBinnedContinuousLegend(*args, domain=domain, **kwargs)
            else:
                value_range = [np.min(dataset.Y), np.max(dataset.Y)]
                return OWContinuousLegend(
                    *args, domain=domain, range=value_range, **kwargs)

class Legend(Anchorable):
    """Base legend class.

    This class provides common attributes for any legend derivates:
      - Behaviour on `QGraphicsScene`
      - Appearance of legend

    If you have access to the `domain` property, the `LegendBuilder` class
    can be used to automatically build a legend for you.

    Parameters
    ----------
    parent : QtGui.QGraphicsItem, optional
    orientation : Qt.Orientation, optional
        The default orientation is vertical
    domain : Orange.data.domain.Domain, optional
        This field is left optional as in some cases, we may want to simply
        pass in a list that represents the legend.
    items : Iterable[QtGui.QColor, str]
    bg_color : QtGui.QColor, optional
    font : QtGui.QFont, optional
    color_indicator_cls : ColorIndicator
        The color indicator class that will be used to render the indicators.

    See Also
    --------
    OWDiscreteLegend
    OWContinuousLegend
    OWContinuousLegend

    Notes
    -----
    .. Warning:: If the domain parameter is supplied, the items parameter will
        be ignored.

    """

    def __init__(self, parent=None, orientation=Qt.Vertical, domain=None,
                 items=None, bg_color=QtGui.QColor(232, 232, 232, 196),
                 font=None, color_indicator_cls=LegendItemSquare, **kwargs):
        super().__init__(parent, **kwargs)

        self.orientation = orientation
        self.bg_color = QtGui.QBrush(bg_color)
        self.color_indicator_cls = color_indicator_cls

        # Set default font if none is given
        if font is None:
            self.font = QtGui.QFont()
            self.font.setPointSize(10)
        else:
            self.font = font

        self.setFlags(QtGui.QGraphicsWidget.ItemIsMovable |
                      QtGui.QGraphicsItem.ItemIgnoresTransformations)

        if domain is not None:
            self.set_domain(domain)
        elif items is not None:
            self.set_items(items)

    def _clear_layout(self):
        self._layout = None
        for child in self.children():
            child.setParent(None)

    def _setup_layout(self):
        self._clear_layout()

        self._layout = QtGui.QGraphicsLinearLayout(self.orientation)
        self._layout.setContentsMargins(10, 5, 10, 5)
        # If horizontal, there needs to be horizontal space between the items
        if self.orientation == Qt.Horizontal:
            self._layout.setSpacing(10)
        # If vertical spacing, vertical space is provided by child layouts
        else:
            self._layout.setSpacing(0)
        self.setLayout(self._layout)

    def set_domain(self, domain):
        """Handle receiving the domain object.

        Parameters
        ----------
        domain : Orange.data.domain.Domain

        Returns
        -------

        Raises
        ------
        AttributeError
            If the domain does not contain the correct type of class variable.

        """
        raise NotImplemented()

    def set_items(self, values):
        """Handle receiving an array of items.

        Parameters
        ----------
        values : iterable[object, QtGui.QColor]

        Returns
        -------

        """
        raise NotImplemented()

    @staticmethod
    def _convert_to_color(obj):
        if isinstance(obj, QtGui.QColor):
            return obj
        elif isinstance(obj, tuple) or isinstance(obj, list):
            assert len(obj) in (3, 4)
            return QtGui.QColor(*obj)
        else:
            return QtGui.QColor(obj)

    def paint(self, painter, options, widget=None):
        painter.save()
        pen = QtGui.QPen(QtGui.QColor(196, 197, 193, 200), 1)
        brush = QtGui.QBrush(QtGui.QColor(self.bg_color))

        painter.setPen(pen)
        painter.setBrush(brush)
        painter.drawRect(self.contentsRect())
        painter.restore()

class OWDiscreteLegend(Legend):
    """Discrete legend.

    See Also
    --------
    Legend
    OWContinuousLegend

    """

    def set_domain(self, domain):
        class_var = domain.class_var

        if not class_var.is_discrete:
            raise AttributeError('[OWDiscreteLegend] The class var provided '
                                 'was not discrete.')

        self.set_items(zip(class_var.values, class_var.colors.tolist()))

    def set_items(self, values):
        self._setup_layout()
        for class_name, color in values:
            legend_item = LegendItem(
                color=self._convert_to_color(color),
                title=class_name,
                parent=self,
                color_indicator_cls=self.color_indicator_cls,
                font=self.font
            )
            self._layout.addItem(legend_item)

class OWContinuousLegend(Legend):
    """Continuous legend.

    See Also
    --------
    Legend
    OWDiscreteLegend

    """

    def __init__(self, *args, **kwargs):
        # Variables used in the `set_` methods must be set before calling super
        self.__range = kwargs.get('range', ())

        super().__init__(*args, **kwargs)

        self._layout.setContentsMargins(10, 10, 10, 10)

    def set_domain(self, domain):
        class_var = domain.class_var

        if not class_var.is_continuous:
            raise AttributeError('[OWContinuousLegend] The class var provided '
                                 'was not continuous.')

        # The first and last values must represent the range, the rest should
        # be dummy variables, as they are not shown anywhere
        values = self.__range

        start, end, pass_through_black = class_var.colors
        # If pass through black, push black in between and add index to vals
        if pass_through_black:
            colors = [self._convert_to_color(c) for c
                      in [start, '#000000', end]]
            values.insert(1, -1)
        else:
            colors = [self._convert_to_color(c) for c in [start, end]]

        self.set_items(list(zip(values, colors)))

    def set_items(self, values):
        vals, colors = list(zip(*values))

        # If the orientation is vertical, it makes more sense for the smaller
        # value to be shown on the bottom
        if self.orientation == Qt.Vertical and vals[0] < vals[len(vals) - 1]:
            colors, vals = list(reversed(colors)), list(reversed(vals))

        self._setup_layout()
        self._layout.addItem(ContinuousLegendItem(
            palette=colors,
            values=vals,
            parent=self,
            font=self.font,
            orientation=self.orientation
        ))

class OWBinnedContinuousLegend(Legend):
    def set_domain(self, domain):
        pass

    def set_items(self, values):
        pass


# -*- coding: utf-8 -*-

from odoo.addons.stock_landed_costs.models import stock_landed_cost
from odoo import models, fields, api, _
from odoo.exceptions import UserError

class StockLandedCost(models.Model):
    _inherit = 'stock.landed.cost'

    READONLY_STATES = {
        'done': [('readonly', True)]
    }

    folder_id = fields.Many2one('incomex.folder', 'Incomex folder')
    purchase_order_ids = fields.One2many('purchase.order', 'landed_cost_id', 'Purchase order', related='folder_id.purchase_order_ids')
    move_ids = fields.One2many('account.move', 'landed_cost_id', 'Expenses invoice')
    lines_summary_ids = fields.One2many('stock.landed.cost.lines.summary', 'cost_id', 'Lines summary',
                            copy=True, default=lambda self: self._get_default_costs(), states=READONLY_STATES)
    landed_cost_summary_ids = fields.One2many('stock.landed.cost.summary', 'cost_id', 'Landed cost summary', copy=True, states=READONLY_STATES)

    def summary_print(self):
        """ Print the invoice and mark it as sent, so that we can see more
            easily the next step of the workflow
        """
        self.ensure_one()
        self.sent = True
        #return self.env['ir.actions.report'].report_action(self, 'proandsys_purchase_14.summary_landed_report')
        return self.env.ref('proandsys_purchase_14.summary_landedcost').report_action(self)

    def _get_default_costs(self):
        lista = []
        for product in self.env['product.product'].search([('landed_cost_ok','=',True)]):
            lista.append((0, 0, {
                'product_id': product.id,
                'split_method': 'by_current_cost_price',
                'name': product.name,
                'price_unit': 0,
                'account_id': product.property_account_expense_id.id or product.categ_id.property_account_expense_categ_id.id
            }))
        return lista

    def compute_landed_cost(self):
        self.compute_lineas()
        res =  super().compute_landed_cost()
        self.compute_summary()
        return res

    def compute_summary(self):
        dic = {}
        lista = []
        for line in self.valuation_adjustment_lines:
            if line.product_id.id not in dic.keys():
                dic[line.product_id.id] = {
                    'product_id': line.product_id.id,
                    'quantity': 0.0,
                    'former_cost': 0.0,
                    'cost_id': self.id,
                    'former_stock_cost': 0.0,
                    'former_stock_quantity': 0.0,
                    'additional_landed_cost': 0.0
                }
            dic[line.product_id.id]['additional_landed_cost'] += line.additional_landed_cost
            dic[line.product_id.id]['quantity'] += line.quantity
            dic[line.product_id.id]['former_cost'] += line.former_cost
            dic[line.product_id.id]['former_stock_quantity'] += line.former_stock_quantity
            dic[line.product_id.id]['former_stock_cost'] += line.former_stock_cost
        if dic:
            self.write({'landed_cost_summary_ids': [(5, 0, 0)]})
            for key,value in dic.items():
                lista += [(0, 0, value)]
            self.landed_cost_summary_ids = lista
        return True

    def _create_accounting_entries(self, move, qty_out):
        if not qty_out:
            qty_out = line.former_stock_quantity - line.product_id.qty_available
        return super()._create_accounting_entries(move, qty_out)

    def button_validate(self):
        res = super().button_validate()
        for cost in self:
            for line in cost.landed_cost_summary_ids:
            ########################################### Aqui corregir #############################################
                line.product_id.standard_price = line.final_stock_cost_per_unit
            #######################################################################################################
        return res

    def compute_lineas(self):
        dic = {}
        if self.lines_summary_ids:
            dic['name'] = 'COSTEO IMPORTACION'
            dic['cost_id'] = self.lines_summary_ids[0].cost_id.id
            dic['product_id'] = self.lines_summary_ids[0].product_id.id
            dic['price_unit'] = sum([a.price_unit for a in self.lines_summary_ids])
            dic['split_method'] = self.lines_summary_ids[0].split_method
            dic['account_id'] = self.lines_summary_ids[0].account_id.id
        if dic:
            self.write({'cost_lines': [(5,0,0)]})
            self.cost_lines.create(dic)
        return True

    def _compute_product_new_cost(self, product_id):
        quant_obj = self.env['stock.quant']
        current_value = 0.0
        quants = quant_obj.search([('product_id','=',product_id.id),('location_id.usage','=','internal')])
        for quant in quants:
            current_value += quant.cost
        return current_value

    def get_valuation_lines(self):
        lines = super().get_valuation_lines()
        for line in lines:
            producto = self.env['product.product'].search([('id','=',line['product_id'])])
            fecha = self.env['stock.move'].browse(line['move_id']).date
            domain = [('product_id','=',producto.id),('state','=','done'),('location_id.usage','not in',['internal','transit']),('location_dest_id.usage','in',['internal','transit']),('date','<=',fecha)]
            entradas = self.env['stock.move'].search(domain)
            salidas = self.env['stock.move'].search(domain)
            cant_entrada = 0
            cant_salida = 0
            if entradas:
                cant_entrada = sum([move.product_qty for move in entradas] or 0)
            if salidas:
                cant_salida = sum([move.product_qty for move in salidas] or 0)
            cant = (cant_entrada-cant_salida)
            line['former_stock_quantity'] = cant
            line['former_stock_cost'] = producto.standard_price * cant
            line['former_stock_cost_per_unit'] = producto.standard_price

        return lines

class SummaryLandedCost(models.Model):
    _name = 'stock.landed.cost.summary'
    _description = "Landed Cost"

    name = fields.Char('Description', related='cost_id.name', store=True)
    cost_id = fields.Many2one('stock.landed.cost', 'Landed cost', ondelete='cascade', required=True)
    currency_id = fields.Many2one('res.currency', 'Currency', related='cost_id.currency_id')
    product_id = fields.Many2one('product.product', 'Product', required=True)
    quantity = fields.Float('Quantity purchased', default=1.0, digits='Product Unit of Measure', required=True)
    weight = fields.Float('Weight', default=1.0, digits='Product Unit of Measure')
    volume = fields.Float('Volume', default=1.0, digits='Product Unit of Measure')
    former_cost = fields.Monetary('Old total cost')
    # former_purchase_cost = fields.Float('Costo original')
    former_cost_per_unit = fields.Monetary('Old unitary cost', compute='_compute_costs', store=True)
    additional_landed_cost = fields.Monetary('Aditional landed cost')
    final_cost = fields.Monetary('Final cost', compute='_compute_costs', store=True)
    final_cost_per_unit = fields.Monetary('New unitary cost', compute='_compute_costs', store=True)
    former_stock_quantity = fields.Float('Original stock quantity')
    former_stock_cost = fields.Float('Original total stock cost')
    former_stock_cost_per_unit = fields.Monetary('Original unitary stock cost', compute='_compute_costs', store=True)
    final_stock_cost = fields.Monetary('Final stock cost', compute='_compute_costs', store=True)
    final_stock_cost_per_unit = fields.Monetary('New unitary stock cost', compute='_compute_costs', store=True)

    @api.depends('former_cost', 'quantity','additional_landed_cost','former_stock_cost','former_stock_quantity')
    def _compute_costs(self):
        for record in self:
            record.former_cost_per_unit = record.former_cost / (record.quantity or 1.0)
            record.final_cost = record.former_cost + record.additional_landed_cost
            record.final_cost_per_unit = (record.former_cost + record.additional_landed_cost) / (record.quantity or 1.0)
            record.former_stock_cost_per_unit = record.former_stock_cost / (record.former_stock_quantity or 1.0)
            record.final_stock_cost = record.former_stock_cost + record.additional_landed_cost
            record.final_stock_cost_per_unit = (record.former_stock_cost + record.additional_landed_cost) / (record.former_stock_quantity or 1.0)

class LandedCostLineSummary(models.Model):
    _name = 'stock.landed.cost.lines.summary'
    _description = 'Stock Landed Cost Lines Summary'

    cost_id = fields.Many2one('stock.landed.cost', 'Landed Cost', ondelete='cascade')
    product_id = fields.Many2one('product.product', 'Product', required=True)
    account_id = fields.Many2one('account.account', 'Account', domain=[('deprecated','=',False)])
    name = fields.Char('Description')
    price_unit = fields.Float('Cost', digits='Costo', required=True)
    split_method = fields.Selection(stock_landed_cost.SPLIT_METHOD, 'Split Method', required=True)

    @api.onchange('product_id')
    def onchange_product_id(self):
        if self.product_id:
            self.name = self.product_id.name or ''
            self.price_unit = self.product_id.standard_price or 0.0
            self.account_id = self.product_id.property_account_expense_id.id or self.product_id.categ_id.property_account_expense_categ_id.id
        else:
            self.quantity = 0.0
            self.price_unit = 0.0

        self.split_method = self.split_method or 'equal'

class AdjustmentLines(models.Model):
    _inherit = 'stock.valuation.adjustment.lines'

    former_stock_quantity = fields.Float('Original stock quantity')
    former_stock_cost = fields.Float('Original total stock cost')
    former_stock_cost_per_unit = fields.Float('Original unitary stock cost')
    final_stock_cost = fields.Float('Final stock cost')
    final_stock_cost_per_unit = fields.Float('New unitary stock cost')

    def _create_account_move_line(self, move, credit_account_id, debit_account_id, qty_out, already_out_account_id):
        """
        Generate the account.move.line values to track the landed cost.
        Afterwards, for the goods that are already out of stock, we should create the out moves
        """
        AccountMoveLine = []

        base_line = {
            'name': self.name,
            'product_id': self.product_id.id,
            'quantity': self.quantity, #Modificado, era 0
        }
        debit_line = dict(base_line, account_id=debit_account_id)
        credit_line = dict(base_line, account_id=credit_account_id)
        diff = self.additional_landed_cost
        if diff > 0:
            debit_line['debit'] = diff
            credit_line['credit'] = diff
        else:
            # negative cost, reverse the entry
            debit_line['credit'] = -diff
            credit_line['debit'] = -diff
        AccountMoveLine.append([0, 0, debit_line])
        AccountMoveLine.append([0, 0, credit_line])

        # Create account move lines for quants already out of stock
        if qty_out > 0:
            debit_line = dict(base_line,
                              name=(self.name + ": " + str(qty_out) + _(' already out')),
                              quantity=qty_out, #Modificado, era 0
                              account_id=already_out_account_id)
            credit_line = dict(base_line,
                               name=(self.name + ": " + str(qty_out) + _(' already out')),
                               quantity=qty_out, #Modificado, era 0
                               account_id=debit_account_id)
            diff = diff * qty_out / (self.former_stock_quantity or 1.0) #Modificado, era "/ self.quantity"
            if diff > 0:
                debit_line['debit'] = diff
                credit_line['credit'] = diff
            else:
                # negative cost, reverse the entry
                debit_line['credit'] = -diff
                credit_line['debit'] = -diff
            AccountMoveLine.append([0, 0, debit_line])
            AccountMoveLine.append([0, 0, credit_line])

            if self.env.company.anglo_saxon_accounting:
                expense_account_id = self.product_id.product_tmpl_id.get_product_accounts()['expense'].id
                debit_line = dict(base_line,
                                  name=(self.name + ": " + str(qty_out) + _(' already out')),
                                  quantity=qty_out, #Modificado, era 0
                                  account_id=expense_account_id)
                credit_line = dict(base_line,
                                   name=(self.name + ": " + str(qty_out) + _(' already out')),
                                   quantity=qty_out, #Modificado, era 0
                                   account_id=already_out_account_id)

                if diff > 0:
                    debit_line['debit'] = diff
                    credit_line['credit'] = diff
                else:
                    # negative cost, reverse the entry
                    debit_line['credit'] = -diff
                    credit_line['debit'] = -diff
                AccountMoveLine.append([0, 0, debit_line])
                AccountMoveLine.append([0, 0, credit_line])
        return AccountMoveLine

class CarpetaImportacion(models.Model):
    _inherit = 'incomex.folder'

    landed_cost_ids = fields.One2many('stock.landed.cost', 'folder_id', 'Landed Cost')


"""
Custom Resource for finding latest the AMI id for a given Description

Parameters:
 * Region: (default: current region)
 * Name: Like: "amzn-ami-minimal-hvm*"
 * OwnerAlias
 * OwnerId
 * Architecture: Defaults to: "x86_64",
 * DeviceType: Defaults to: "ebs",
 * VirtualizationType: Defaults to: "hvm",
 * State: Defaults to: 'available',
"""

import os
import boto3
import structlog

from cfn_custom_resource import CloudFormationCustomResource
from _metadata import CUSTOM_RESOURCE_NAME

REGION = os.environ['AWS_REGION']

structlog.configure(processors=[structlog.processors.JSONRenderer()])

def dict_element_copy_if_exists(
        source_dict: dict, source_key: str,
        target_dict: dict, target_key: str):
    if source_key in source_dict:
        target_dict[target_key] = source_dict[source_key]

class FindAmi(CloudFormationCustomResource):
    RESOURCE_TYPE_SPEC = CUSTOM_RESOURCE_NAME
    DISABLE_PHYSICAL_RESOURCE_ID_GENERATION = True  # Return AMI ID as physical ID

    def validate(self):
        self.filter = {}

        try:
            self.filter['name'] = self.resource_properties['Name']
            dict_element_copy_if_exists(
                self.resource_properties, 'OwnerAlias',
                self.filter, 'owner-alias'
            )
            dict_element_copy_if_exists(
                self.resource_properties, 'OwnerId',
                self.filter, 'owner-id'
            )
            self.filter['architecture'] = self.resource_properties.get('Architecture', 'x86_64')
            self.filter['root-device-type'] = self.resource_properties.get('DeviceType', 'ebs')
            self.filter['virtualization-type'] = self.resource_properties.get('VirtualizationType', 'hvm')
            self.filter['state'] = self.resource_properties.get('State', 'available')
            return True

        except (AttributeError, KeyError):
            return False

    def create(self):
        structlog.get_logger().log("Handling request", filter=self.filter)
        ec2_client = boto3.client(  # Don't use self.get_boto3_client, since we may vary regions
            'ec2',
            region_name=self.resource_properties.get('Region', REGION),
        )

        ami_filter = []
        for key, value in self.filter.items():
            ami_filter.append({
                'Name': key,
                'Values': [value],
            })

        structlog.get_logger().log("Converted to AMI filter; doing API call", filter=ami_filter)
        ami_list = ec2_client.describe_images(
            Filters=ami_filter
        )
        structlog.get_logger().log("API call done, sorting")
        sorted_ami_list = sorted(
            ami_list['Images'],
            key=lambda k: k.get('CreationDate', ''),
            reverse=True
        )
        if len(sorted_ami_list) == 0:
            self.status = self.STATUS_FAILED
            self.failure_reason = "No image found matching filters."
            return {}

        latest_ami = sorted_ami_list[0]
        self.physical_resource_id = latest_ami['ImageId']
        return {}

    def update(self):
        return self.create()

    def delete(self):
        # Nothing to delete
        pass

handler = FindAmi.get_handler()


import contextlib
from typing import List, Any, Dict

import ray
import ray.cloudpickle
from ray.util.serialization import register_serializer, deregister_serializer

from ray.experimental.workflow.common import Workflow, WorkflowInputs

def _resolve_workflow_outputs(index: int) -> Any:
    raise ValueError("There is no context for resolving workflow outputs.")

def _resolve_objectrefs(index: int) -> ray.ObjectRef:
    raise ValueError("There is no context for resolving object refs.")

@contextlib.contextmanager
def workflow_args_serialization_context(
        workflows: List[Workflow], object_refs: List[ray.ObjectRef]) -> None:
    """
    This serialization context reduces workflow input arguments to three
    parts:

    1. A workflow input placeholder. It is an object without 'Workflow' and
       'ObjectRef' object. They are replaced with integer indices. During
       deserialization, we can refill the placeholder with a list of
       'Workflow' and a list of 'ObjectRef'. This provides us great
       flexibility, for example, during recovery we can plug an alternative
       list of 'Workflow' and 'ObjectRef', since we lose the original ones.
    2. A list of 'Workflow'. There is no duplication in it.
    3. A list of 'ObjectRef'. There is no duplication in it.

    We do not allow duplication because in the arguments duplicated workflows
    and object refs are shared by reference. So when deserialized, we also
    want them to be shared by reference. See
    "tests/test_object_deref.py:deref_shared" as an example.

    The deduplication works like this:
        Inputs: [A B A B C C A]
        Output List: [A B C]
        Index in placeholder: [0 1 0 1 2 2 0]

    Args:
        workflows: Workflow list output.
        object_refs: ObjectRef list output.
    """
    workflow_deduplicator: Dict[Workflow, int] = {}
    objectref_deduplicator: Dict[ray.ObjectRef, int] = {}

    def workflow_serializer(workflow):
        if workflow in workflow_deduplicator:
            return workflow_deduplicator[workflow]
        i = len(workflows)
        workflows.append(workflow)
        workflow_deduplicator[workflow] = i
        return i

    register_serializer(
        Workflow,
        serializer=workflow_serializer,
        deserializer=_resolve_workflow_outputs)

    def objectref_serializer(obj_ref):
        if obj_ref in objectref_deduplicator:
            return objectref_deduplicator[obj_ref]
        i = len(object_refs)
        object_refs.append(obj_ref)
        objectref_deduplicator[obj_ref] = i
        return i

    # override the default ObjectRef serializer
    # TODO(suquark): We are using Ray internal APIs to access serializers.
    # This is only a workaround. We need alternatives later.
    ray_objectref_reducer_backup = ray.cloudpickle.CloudPickler.dispatch[
        ray.ObjectRef]
    register_serializer(
        ray.ObjectRef,
        serializer=objectref_serializer,
        deserializer=_resolve_objectrefs)

    try:
        yield
    finally:
        # we do not want to serialize Workflow objects in other places.
        deregister_serializer(Workflow)
        # restore original dispatch
        ray.cloudpickle.CloudPickler.dispatch[
            ray.ObjectRef] = ray_objectref_reducer_backup

@contextlib.contextmanager
def workflow_args_resolving_context(
        workflow_output_mapping: List[Any],
        objectref_mapping: List[ray.ObjectRef]) -> None:
    """
    This context resolves workflows and objectrefs inside workflow
    arguments into correct values.

    Args:
        workflow_output_mapping: List of workflow outputs.
        objectref_mapping: List of object refs.
    """
    global _resolve_workflow_outputs, _resolve_objectrefs
    _resolve_workflow_outputs_bak = _resolve_workflow_outputs
    _resolve_objectrefs_bak = _resolve_objectrefs

    _resolve_workflow_outputs = workflow_output_mapping.__getitem__
    _resolve_objectrefs = objectref_mapping.__getitem__

    try:
        yield
    finally:
        _resolve_workflow_outputs = _resolve_workflow_outputs_bak
        _resolve_objectrefs = _resolve_objectrefs_bak

class _KeepWorkflowOutputs:
    def __init__(self, index: int):
        self._index = index

    def __reduce__(self):
        return _resolve_workflow_outputs, (self._index, )

class _KeepObjectRefs:
    def __init__(self, index: int):
        self._index = index

    def __reduce__(self):
        return _resolve_objectrefs, (self._index, )

@contextlib.contextmanager
def workflow_args_keeping_context() -> None:
    """
    This context only read workflow arguments. Workflows and objectrefs inside
    are untouched and can be serialized again properly.
    """
    global _resolve_workflow_outputs, _resolve_objectrefs
    _resolve_workflow_outputs_bak = _resolve_workflow_outputs
    _resolve_objectrefs_bak = _resolve_objectrefs

    # we must capture the old functions to prevent self-referencing.
    def _keep_workflow_outputs(index: int):
        return _KeepWorkflowOutputs(index)

    def _keep_objectrefs(index: int):
        return _KeepObjectRefs(index)

    _resolve_workflow_outputs = _keep_workflow_outputs
    _resolve_objectrefs = _keep_objectrefs

    try:
        yield
    finally:
        _resolve_workflow_outputs = _resolve_workflow_outputs_bak
        _resolve_objectrefs = _resolve_objectrefs_bak

def make_workflow_inputs(args_list: List[Any]) -> WorkflowInputs:
    workflows: List[Workflow] = []
    object_refs: List[ray.ObjectRef] = []
    with workflow_args_serialization_context(workflows, object_refs):
        # NOTE: When calling 'ray.put', we trigger python object
        # serialization. Under our serialization context,
        # Workflows and ObjectRefs are separated from the arguments,
        # leaving a placeholder object with all other python objects.
        # Then we put the placeholder object to object store,
        # so it won't be mutated later. This guarantees correct
        # semantics. See "tests/test_variable_mutable.py" as
        # an example.
        input_placeholder: ray.ObjectRef = ray.put(args_list)
        if object_refs:
            raise ValueError(
                "There are ObjectRefs in workflow inputs. However "
                "workflow currently does not support checkpointing "
                "ObjectRefs.")
    return WorkflowInputs(input_placeholder, object_refs, workflows)


import tkinter as tk
import tkinter.ttk as ttk

import controls
import turtlechart

class MainApplication(ttk.Frame):
    """Main widget for application

    A Frame that contains the Controls and TurtleChart widgets.
    """
    def __init__(self, parent):
        """Main constructor
        Calls parent constructor, creates widgets (Controls and TurtleChart),
        and sets widget layouts.
        """
        ttk.Frame.__init__(self, parent, padding=5)

        # widgets
        self.controls = controls.Controls(self)
        self.turtlechart = turtlechart.TurtleChart(self)

        # layouts
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(1, weight=1)
        self.grid(sticky='nsew')
        self.controls.grid(row=0, column=0)
        self.turtlechart.grid(row=1, column=0)

def main():
    root = tk.Tk()
    root.grid_columnconfigure(0, weight=1)
    root.grid_rowconfigure(0, weight=1)
    root.title('Pie Chart')
    app = MainApplication(root)
    app.mainloop()

if __name__ == "__main__":
    main()


import argparse
import re
import glob
import sys
import pickle

_dictionary = {}
a = []

# разбиваем строку на слова, опционально приводим к нижнему регистру
def correct_line(line, lowercase):
    line = re.sub(r'[^A-Za-zА-Яа-я ]', '', line)
    line = re.sub(r'\s+', ' ', line)
    if lowercase:
        line = line.lower()
    return line.strip().split()

# создаем словарь {слово1 : {слово2 : частота...}...}
def create_dict(a, dictionary):
    flag = 0
    global ending_word
    for i in range(len(a)):
        word2 = a[i]
        if flag == 0:
            word1 = ending_word
        elif flag == len(a) - 1:
            word1 = a[i - 1]
            ending_word = word2
        else:
            word1 = a[i - 1]
        if word1 != "":
            if dictionary.get(word1) is not None:
                if dictionary.get(word1).get(word2) is not None:
                    dictionary.get(word1)[word2] += 1
                else:
                    dictionary.get(word1).setdefault(word2, 1)
            else:
                default = {word2: 1}
                dictionary.setdefault(word1, default)
        flag += 1
    return dictionary

parser = argparse.ArgumentParser(description='Create a model.')
parser.add_argument(
    '--input-dir',
    dest='inp',
    default='stdin',
    help='input a path to the directory (else stdin)')
parser.add_argument(
    '--model',
    dest='mo',
    required=True,
    help='input a path to the file with model')
parser.add_argument(
    '--lc',
    action='store_true',
    default=False,
    help='converts text to lowercase')
args = parser.parse_args()
lowercase = args.lc

if args.inp != 'stdin':
    path = args.inp
    # извлекаем все файлы из указанной директории
    files = glob.glob(pathname=path)
    for name in files:
        ending_word = ''
        with open(name, encoding='ANSI') as f:
            for line in f:
                a = correct_line(line, lowercase)
                _dictionary = create_dict(a, _dictionary)
else:
    ending_word = ''
    for line in sys.stdin:
        correct_line(line, lowercase)
        _dictionary = create_dict(a, _dictionary)
model = args.mo
with open(model, 'wb') as t:    # сохраняем словарь в указанный файл
    pickle.dump(_dictionary, t)


from tkinter import *

def miles_to_km():
 km = km_input.get()
 miles = float(km)*0.6214
 mile_result.config(text=f"{miles}")

window = Tk()
window.title("Miles to Kilometre Converter")
window.configure(padx=20, pady=20)

km_input = Entry(width=5)
km_input.grid(column=1, row=0)

kilometer_label = Label(text="Km")
kilometer_label.grid(column=2, row=0)

is_equal_label = Label(text="is equal to")
is_equal_label.grid(column=0,row=1)

mile_result = Label(text="0")
mile_result.grid(column=1, row=1)

mile_label = Label(text="Miles")
mile_label.grid(column=2, row=1)

calculate_button = Button(text="Calculate", command = miles_to_km)
calculate_button.grid(column=1,row=2)

window.mainloop()

Day 27 Km to Miles Converter GUI Project/main.py


#!/usr/bin/env python3

import dadi
import dadi.Godambe
import numpy as np

def divergence(params, ns, pts):
    """
    Divergence only model.
    """
    nuTX,nuFL,T1,T2,F1,F2 = params

    xx = yy = dadi.Numerics.default_grid(pts)
    n1,n2 = ns[0],ns[1]

    phi = dadi.PhiManip.phi_1D(xx)
    phi = dadi.Integration.one_pop(phi,xx,T1,nu=nuTX)
    phi = dadi.PhiManip.phi_1D_to_2D(xx,phi)

    phi = dadi.Integration.two_pops(phi,xx,T2,nu1=nuTX,nu2=nuFL)
    sfs = dadi.Spectrum.from_phi_inbreeding(phi, (n1,n2), (xx,yy), (F1,F2), (2,2))
    return sfs

if __name__ == '__main__':
    # Read in the bootstrapped spectra and then fold
    all_boot = [dadi.Spectrum.from_file("boot/puma_test2_boot{}.fs".format(i)) for i in range(100)]
    all_boot = [sfs.fold() for sfs in all_boot]

    # Now read in the original data set
    data = dadi.Spectrum.from_file("puma.fs")
    data = data.fold()
    pts_l = [40,50,60]
    func = divergence
    popt = [0.5439309410920344,0.0120104498902649,0.3154710478935099,0.0100122945339300,0.43951783360569285,0.606535498834911]

    func_ex = dadi.Numerics.make_extrap_log_func(func)

    # Calculate parameter uncertainties
    """
    We include this section to check uncertainties across different step sizes (eps).
    This can be turned off by setting check_grid_size=False.
    """
    check_grid_sizes = False
    if check_grid_sizes:
        print("\nChecking uncertainties with different grid sizes:")
        for e in [1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7]:
    	    u = dadi.Godambe.GIM_uncert(func_ex, pts_l, all_boot, popt, data, log=True, multinom=True, eps=e)
    	    print("{} = {}".format(e,u))
        exit(0)

    eps=1e-2 # the default is 1e-2
    uncerts,GIM = dadi.Godambe.GIM_uncert(func_ex, pts_l, all_boot, popt, data, log=True, multinom=True, return_GIM=True)
    vcov = np.linalg.inv(GIM)

    llik_F   = -318058.079230279
    llik_noF = -453003.047885215
    adj      = dadi.Godambe.LRT_adjust(func_ex, pts_l, all_boot, popt, data, nested_indices=[4,5], multinom=True)
    D_adj    = 2 * adj * (llik_F - llik_noF)
    print("\n\nLikelihood ratio test:")
    print("  No inbreeding likelihood = {:0.3f}".format(llik_noF))
    print("  Inbreeding likelihood    = {:0.3f}".format(llik_F))
    print("  LRT adjustment           = {:0.3f}".format(adj))
    print("  LRT statistic            = {:0.3f}".format(D_adj))
    print("  LRT p-value              = {:0.3f}".format(dadi.Godambe.sum_chi2_ppf(D_adj, (1.0/4.0,1.0/2.0,1.0/4.0))))

    # Set conversion parameters
    theta = 2939439.410209113 # estimated from model
    L = 2564692624
    mu = 2.2e-9
    g  = 3 # generation time
    scalar = L*mu*4
    Nref = theta / scalar
    print("\n\nConverting parameters to actual units (eps={})...\n".format(eps))
    print("Using the following values for conversion:")
    print("  Sequence length = {}".format(L))
    print("  Mutation rate   = {}".format(mu))
    print("  Generation time = {}".format(g))
    print("")

    uncerts2 = [
        np.sqrt(vcov[-1,-1] + vcov[0,0] + 2*vcov[0,-1]),
        np.sqrt(vcov[-1,-1] + vcov[1,1] + 2*vcov[1,-1]),
        np.sqrt(vcov[-1,-1] + vcov[2,2] + 2*vcov[2,-1]),
        np.sqrt(vcov[-1,-1] + vcov[3,3] + 2*vcov[3,-1]),
        uncerts[4],
        uncerts[5],
        uncerts[-1]
    ]

    log_params = [
        np.log(theta) + np.log(popt[0]) + np.log(1/scalar),   # N_TX
        np.log(theta) + np.log(popt[1]) + np.log(1/scalar),   # N_FL
        np.log(theta) + np.log(popt[2]) + np.log(2*g/scalar), # T1
        np.log(theta) + np.log(popt[3]) + np.log(2*g/scalar), # T2
    ]

    print("Estimated parameter standard deviations from GIM:\n{}\n".format(uncerts))
    print("Estimated parameter standard deviations from error propagation:\n{}\n".format(uncerts2))
    print("Variance-Covariance Matrix:\n{}\n".format(vcov))

    """
    With propogation of uncertainty
    """
    print("\nParameter estimates and 95% confidence intervals:")
    print("Nref = {} ({}--{})".format(Nref, np.exp(np.log(theta)-1.96*uncerts2[-1])/scalar, np.exp(np.log(theta)+1.96*uncerts2[-1])/scalar))
    print("N_TX = {} ({}--{})".format(popt[0]*Nref, np.exp(log_params[0]-1.96*uncerts2[0]), np.exp(log_params[0]+1.96*uncerts2[0])))
    print("N_FL = {} ({}--{})".format(popt[1]*Nref, np.exp(log_params[1]-1.96*uncerts2[1]), np.exp(log_params[1]+1.96*uncerts2[1])))
    print("T1   = {} ({}--{})".format(popt[2]*2*g*Nref, np.exp(log_params[2]-1.96*uncerts2[2]), np.exp(log_params[2]+1.96*uncerts2[2])))
    print("T2   = {} ({}--{})".format(popt[3]*2*g*Nref, np.exp(log_params[3]-1.96*uncerts2[3]), np.exp(log_params[3]+1.96*uncerts2[3])))
    print("F1   = {} ({}--{})".format(popt[4], np.exp(np.log(popt[4])-1.96*uncerts2[4]), np.exp(np.log(popt[4])+1.96*uncerts2[4])))
    print("F2   = {} ({}--{})".format(popt[5], np.exp(np.log(popt[5])-1.96*uncerts2[5]), np.exp(np.log(popt[5])+1.96*uncerts2[5])))


__author__ = 'tmnkv'

class EmptyError(Exception): pass

def upper_list_from_file(filename):
    fh = None
    lines = []
    try:
        fh = open(filename, encoding="utf8")
        for line in fh:
            lines.append(line.strip().upper())
    except (IOError, OSError) as err:
        print(err)
        return []
    else:
        lines.sort()
    finally:
        if fh is not None:
            fh.close()
    return lines

try:
    lst = ["cat", "", "table", "sky", "1234", "phone"]
    for element in lst:
        if len(element) == 0:
            raise EmptyError()
except EmptyError:
    print("there is an empty element, check the list")
else:
    print("no empty elements")

print(upper_list_from_file("lower_file"))


import json
import os

import pytest

import state
from protocol import CloudNodeProtocol
from new_message import process_new_message
from message import Message, ClientType, ActionType, LibraryActionType, ErrorType

@pytest.fixture(scope="module")
def dummy_client():
    return CloudNodeProtocol()

@pytest.fixture(scope="module")
def library_registration_message(repo_id, api_key):
    return Message.make({
        "type": "REGISTER",
        "node_type": "library",
        "repo_id": repo_id,
        "api_key": api_key,
        "is_demo": False
    })

@pytest.fixture(scope="module")
def bad_registration_message(repo_id):
    return Message.make({
        "type": "REGISTER",
        "node_type": "library",
        "repo_id": repo_id,
        "api_key": "bad-api-key",
        "is_demo": "False"
    })

@pytest.fixture(scope="module")
def dashboard_registration_message(repo_id, api_key):
    return Message.make({
        "type": "REGISTER",
        "node_type": "dashboard",
        "repo_id": repo_id,
        "api_key": api_key,
        "is_demo": False
    })

@pytest.fixture(scope="module")
def do_nothing():
    return {
        "action": None
    }

@pytest.fixture(scope="module")
def registration_success():
    return {
        "action": ActionType.UNICAST,
        "message": {
            "action": LibraryActionType.REGISTRATION_SUCCESS.value,
            "error": False,
        }
    }

@pytest.fixture(scope="module")
def failed_authentication_error():
    return {
        "error": True,
        "error_message": "API key provided is invalid!",
        "type": ErrorType.AUTHENTICATION.value,
    }

@pytest.fixture(scope="module")
def duplicate_client_error():
    return {
        "error": True,
        "error_message": "Client already exists!",
        "type": ErrorType.REGISTRATION.value,
    }

@pytest.fixture(scope="module")
def only_one_dashboard_client_error():
    return {
        "error": True,
        "error_message": "Only one DASHBOARD client allowed at a time!",
        "type": ErrorType.REGISTRATION.value,
    }

@pytest.fixture(scope="module")
def original_client_count(factory, repo_id):
    return _client_count(factory, repo_id)

@pytest.fixture(autouse=True)
def unregister(factory, repo_id, dummy_client):
    yield
    clients = factory.clients[repo_id][ClientType.LIBRARY]
    if dummy_client in clients:
        clients.remove(dummy_client)

def test_basic_register(library_registration_message, factory, dummy_client, \
        registration_success, original_client_count):
    """
    Test that a basic `LIBRARY` registration succeeds.
    """
    repo_id = library_registration_message.repo_id
    results = process_new_message(library_registration_message, factory, \
        dummy_client)
    new_client_count = _client_count(factory, repo_id)

    assert results == registration_success, \
        "Resulting message is incorrect!"
    assert new_client_count == original_client_count + 1, \
        "Client count is incorrect!"

def test_failed_authentication(bad_registration_message, factory, \
        dummy_client, failed_authentication_error, original_client_count):
    """
    Test that registration fails with an invalid API key
    """
    repo_id = bad_registration_message.repo_id
    bad_registration_message.api_key = "bad-api-key"
    results = process_new_message(bad_registration_message, factory, \
        dummy_client)
    new_client_count = _client_count(factory, repo_id)

    assert results.get("message") == failed_authentication_error, \
        "Resulting message is incorrect!"
    assert new_client_count == original_client_count, \
        "Client count is incorrect!"

def test_no_duplicate_client(library_registration_message, factory, \
        dummy_client, duplicate_client_error, original_client_count):
    """
    Test that a client cannot be registered twice.
    """
    repo_id = library_registration_message.repo_id
    results = process_new_message(library_registration_message, factory, \
        dummy_client)
    results = process_new_message(library_registration_message, factory, \
        dummy_client)
    new_client_count = _client_count(factory, repo_id)

    assert results.get("message") == duplicate_client_error, \
        "Resulting message is incorrect!"
    assert new_client_count == original_client_count + 1, \
        "Client count is incorrect!"

def test_only_one_dashboard_client(dashboard_registration_message, factory, \
        dummy_client, only_one_dashboard_client_error, original_client_count):
    """
    Test that more than one dashboard client cannot be registered at a time.
    """
    repo_id = dashboard_registration_message.repo_id
    assert _client_count(factory, repo_id) == original_client_count
    results = process_new_message(dashboard_registration_message, factory, \
        dummy_client)
    new_client_count = _client_count(factory, repo_id)

    assert results.get("message") == only_one_dashboard_client_error, \
        "Resulting message is incorrect!"
    assert new_client_count == original_client_count, \
        "Client count is incorrect!"

def _client_count(factory, repo_id):
    """
    Helper function to count the total number of clients in the factory.
    """
    return len(factory.clients[repo_id][ClientType.DASHBOARD]) \
        + len(factory.clients[repo_id][ClientType.LIBRARY])


#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

import torch
import torch.nn as nn

# 实现一个nn.Module, 需要实现init, forward
class ClassyBlock(nn.Module):
    """
    This is a thin wrapper for head execution, which records the output of
    wrapped module for executing the heads forked from this module.
    """

    def __init__(self, name, module):
        super().__init__()
        self.name = name
        self.output = torch.zeros(0)
        self._module = module
        self._should_cache_output = False

    # 是否缓存中间变量
    def set_cache_output(self, should_cache_output: bool = True):
        """
        Whether to cache the output of wrapped module for head execution.
        """
        self._should_cache_output = should_cache_output

    def forward(self, input):
        output = self._module(input)
        if self._should_cache_output:
            self.output = output
        return output


"""This class was taken from the matplotlib site from the Lasso Selector Demo
    https://matplotlib.org/3.1.1/gallery/widgets/lasso_selector_demo_sgskip.html
"""

import numpy as np
from matplotlib.widgets import LassoSelector
from matplotlib.path import Path

class SelectFromCollection(object):
    """Select indices from a matplotlib collection using `LassoSelector`.

    Selected indices are saved in the `ind` attribute. This tool fades out the
    points that are not part of the selection (i.e., reduces their alpha
    values). If your collection has alpha < 1, this tool will permanently
    alter the alpha values.

    Note that this tool selects collection objects based on their *origins*
    (i.e., `offsets`).

    Parameters
    ----------
    ax : :class:`~matplotlib.axes.Axes`
        Axes to interact with.

    collection : :class:`matplotlib.collections.Collection` subclass
        Collection you want to select from.

    alpha_other : 0 <= float <= 1
        To highlight a selection, this tool sets all selected points to an
        alpha value of 1 and non-selected points to `alpha_other`.
    """

    def __init__(self, ax, collection, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.alpha_other = alpha_other

        self.xys = collection.get_offsets()
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object
        self.fc = collection.get_facecolors()
        if len(self.fc) == 0:
            raise ValueError('Collection must have a facecolor')
        elif len(self.fc) == 1:
            self.fc = np.tile(self.fc, (self.Npts, 1))

        self.lasso = LassoSelector(ax, onselect=self.onselect)
        self.ind = []

    def onselect(self, verts):
        path = Path(verts)
        self.ind = np.nonzero(path.contains_points(self.xys))[0]
        self.fc[:, -1] = self.alpha_other
        self.fc[self.ind, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()

    def disconnect(self):
        self.lasso.disconnect_events()
        self.fc[:, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()


import datetime as dt
import random
from functools import cached_property

from data import LOCATIONS, DATE_LOOKUP

class Date:
    def __init__(self, year, month, day, location=None, is_gregorian=True):
        self.year = year  # Year 0 is 1 BCE
        self.month = month
        self.day = day
        self.location = location
        self.is_gregorian = is_gregorian

    def __str__(self):
        result = self._date.strftime("%d. %B ")
        if self.year < 1:
            result += f"{abs(year) + 1} BCE"
        else:
            result += str(abs(self.year))
        if self.location:
            result += f" in {self.location}"
        return result

    @cached_property
    def _date(self):
        return dt.date(self.year if self.year > 0 else abs(self.year) + 1, self.month, self.day)

    @cached_property
    def is_leap_year(self):
        return is_leap_year(self.year, self.is_gregorian)

    @cached_property
    def weekday(self):
        """Monday is 0, Sunday is 6"""
        # we could use .weekday() plus an adjustment value down to the year 0, but
        # not before that, so let's just use the stupid table, I guess
        total = 0
        centuries = int(self.year / 100)
        years = self.year % 100
        if self.is_gregorian:
            total += DATE_LOOKUP["centuries_gregorian"][centuries % 4]
        else:
            total += DATE_LOOKUP["centuries_julian"][centuries % 7]
        total += DATE_LOOKUP["years"][years]
        if self.is_leap_year:
            total += DATE_LOOKUP["months_leap"][self.month]
        else:
            total += DATE_LOOKUP["months"][self.month]
        total += self.day
        return DATE_LOOKUP["weekday"][total % 7]

    @cached_property
    def weekday_string(self):
        return [
            "Monday",
            "Tuesday",
            "Wednesday",
            "Thursday",
            "Friday",
            "Saturday",
            "Sunday",
        ][self.weekday]

def get_random_date():
    """
    You'd think that grabbing a random date is easy, wouldn't you?

    First off, a qualifier: Picking a random /European/ date.
    This excludes non-European calendars, and calendar reforms
    in the colonies, because I can't be arsed to learn those.

    We're starting by picking a year and a month at random, because
    those always exist, thank fuck. Now, we can't pick a random
    day next, because the available days depend on the calendar
    in use, which, between 1582 and 1924, depends on the location.
    So we pick a location, and then we can make sure that
    a) we're not using leap days that did not exist, and b)
    that our random date did actually occur.

    I'm tempted to add a mode where "Trick question, this date did
    not occur" is a valid answer.

    Some of this is imprecise, because I can't be arsed to make
    sure countries are only included when they actually existed.
    """
    year = random.randrange(-44, dt.date.today().year + 200)
    month = random.randrange(1, 13)
    day = None
    location = None

    if (1582, 10) <= (year, month) <= (1924, 10):
        # uhhhm, where are we
        location = random.choice(list(LOCATIONS.keys()))
        julian_end, gregorian_start = LOCATIONS[location]

        if (year, month) < (julian_end[0], julian_end[1]):  # easy
            is_gregorian = False
        elif (year, month) > (gregorian_start[0], gregorian_start[1]):  # easy
            is_gregorian = True
        else:  # aw man
            if (
                year == julian_end[0] and month == julian_end[1]
            ):  # Biased towards Julian calendar, wooo
                is_gregorian = False
                day = random.randrange(1, julian_end[2] + 1)
            else:
                is_gregorian = True
                day = (
                    gregorian_start[2]
                    if gregorian_start[2] > 28
                    else random.randrange(gregorian_start[2], 29)
                )  # nothing to see here
    else:
        is_gregorian = year > 1800  # things could be so simple

    if not day:
        day = get_random_day(year, month, is_gregorian=is_gregorian)

    return Date(
        year=year, month=month, day=day, location=location, is_gregorian=is_gregorian
    )

def is_leap_year(year, is_gregorian):
    if is_gregorian:
        try:
            dt.date(year, 2, 29)
            return True
        except ValueError:
            return False
    return year % 4 == 0

def get_random_day(month, year, is_gregorian):
    if month != 2:  # We should be so lucky
        max_days = 30 if month in (4, 6, 9, 11) else 31
    else:
        max_days = 29 if is_leap_year(year, is_gregorian) else 28
    return random.randrange(1, max_days + 1)

def main():
    date = get_random_date()
    print(date)

if __name__ == "__main__":
    main()


#!/usr/bin/python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
### BEGIN LICENSE
# Copyright (C) 2013 <Zane Swafford> <zane@zaneswafford.com>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
### END LICENSE
from gi.repository import GdkPixbuf
from spindl_lib.treeviewFormat import format_column
from timeFormat import time_in_span, tuple_time, unformat_time
from math import ceil

class TrendView:
	def __init__(self, treeview_window, treestore, activity_cellrenderedtext,
					trend_pixbuf, percent_change_cellrenderedtext, image_directory):
		self.treeview_window = treeview_window
		self.treestore = treestore
		self.activity_cellrenderedtext = activity_cellrenderedtext
		self.trend_pixbuf = trend_pixbuf
		self.percent_change_cellrenderedtext = percent_change_cellrenderedtext
		self.data = []
		# Make the trendview visible by default
		self.visible = True
		# Load up the pixbufs
		self.image_directory = image_directory
		self.up_pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.image_directory + 'up.png')
		self.same_pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.image_directory + 'same.png')
		self.down_pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.image_directory + 'down.png')
		# Format the treeview_window
		format_column(None, None, self.activity_cellrenderedtext,
					self.percent_change_cellrenderedtext, self.trend_pixbuf)

	def generate_day_trends(self, date):
		"""Takes logs from self.data and changes them to activity trends for
		since the previous day based on a given date tuple"""
		day_activity_list = []
		previous_day_activity_list = []
		trends = []
		# Iterate through the log data.
		for log in self.data:
			# Get and format the information we need from the log.
			activity = log[0]
			log_start = unformat_time(tuple_time(log[1]))
			log_end = unformat_time(tuple_time(log[2]))
			minimum = unformat_time((0,0,0,date[0],date[1],date[2]))
			maximum = unformat_time((59,59,23,date[0],date[1],date[2]))
			# Add the time and activity to the chart_list.
			log_time = time_in_span(log_start, log_end, minimum, maximum)
			# Check if the activity has already been added to chart_list.
			in_day_activity_list = False
			for entry in day_activity_list:
				# If the activity is in the chart_list, make a note and add.
				# its time to the existing list item.
				if entry[0] == activity:
					entry[1] += log_time
					in_day_activity_list = True
			# If the log is not in the chart_list and it is in the span, add
			# it to the chart_list.
			if not in_day_activity_list and log_time > 0:
				day_activity_list.append([activity, log_time])
		# Iterate through the log data.
		for log in self.data:
			# Get and format the information we need from the log.
			activity = log[0]
			log_start = unformat_time(tuple_time(log[1]))
			log_end = unformat_time(tuple_time(log[2]))
			minimum = unformat_time((0,0,0,date[0],date[1],date[2]))
			minimum -= unformat_time((0,0,0,1,0,0))
			maximum = unformat_time((59,59,23,date[0],date[1],date[2]))
			maximum -= unformat_time((0,0,0,1,0,0))
			# Add the time and activity to the chart_list.
			log_time = time_in_span(log_start, log_end, minimum, maximum)
			# Check if the activity has already been added to chart_list.
			in_previous_day_activity_list = False
			for entry in previous_day_activity_list:
				# If the activity is in the chart_list, make a note and add.
				# its time to the existing list item.
				if entry[0] == activity:
					entry[1] += log_time
					in_previous_day_activity_list = True
			# If the log is not in the chart_list and it is in the span, add
			# it to the chart_list.
			if not in_previous_day_activity_list and log_time > 0:
				previous_day_activity_list.append([activity, log_time])
		# Search through the day_activity_list and previous_day_activity_list
		# for matching activities
		for activity in day_activity_list:
			for previous_activity in previous_day_activity_list:
				if activity[0] == previous_activity[0]:
					# Get the percent change between the two activities' times
					# as a string in the form of 100.00%
					percent_change = (((activity[1]-previous_activity[1])*1.00)
										/(previous_activity[1]*1.00))
					percent_change = str((ceil(percent_change*10000.00))/100.00)
					if percent_change[-2] == '.':
						percent_change += '0'
					percent_change += '%'
					# Add this activity and it's percent change to trends list
					trends.append([activity[0], percent_change])
		# Set data as trends
		self.data = trends

	def generate_month_trends(self, date):
		"""Takes logs from self.data and changes them to activity trends for
		since the previous month based on a given date tuple"""
		month_activity_list = []
		previous_month_activity_list = []
		trends = []
		# Iterate through the log data.
		for log in self.data:
			# Get and format the information we need from the log.
			activity = log[0]
			log_start = unformat_time(tuple_time(log[1]))
			log_end = unformat_time(tuple_time(log[2]))
			minimum = unformat_time((0,0,0,1,date[1],date[2]))
			maximum = unformat_time((59,59,23,date[0],date[1],date[2]))
			# Add the time and activity to the chart_list.
			log_time = time_in_span(log_start, log_end, minimum, maximum)
			# Check if the activity has already been added to chart_list.
			in_month_activity_list = False
			for entry in month_activity_list:
				# If the activity is in the chart_list, make a note and add.
				# its time to the existing list item.
				if entry[0] == activity:
					entry[1] += log_time
					in_month_activity_list = True
			# If the log is not in the chart_list and it is in the span, add
			# it to the chart_list.
			if not in_month_activity_list and log_time > 0:
				month_activity_list.append([activity, log_time])
		# Iterate through the log data.
		for log in self.data:
			# Get and format the information we need from the log.
			activity = log[0]
			log_start = unformat_time(tuple_time(log[1]))
			log_end = unformat_time(tuple_time(log[2]))
			if date[1] > 1:
				minimum = unformat_time((0,0,0,1,date[1]-1,date[2]))
			else:
				minimum = unformat_time((0,0,0,1,12,date[2]-1))
			maximum = unformat_time((59,59,23,1,date[1],date[2]))
			maximum -= unformat_time((0,0,0,1,0,0))
			# Add the time and activity to the chart_list.
			log_time = time_in_span(log_start, log_end, minimum, maximum)
			# Check if the activity has already been added to chart_list.
			in_previous_month_activity_list = False
			for entry in previous_month_activity_list:
				# If the activity is in the chart_list, make a note and add.
				# its time to the existing list item.
				if entry[0] == activity:
					entry[1] += log_time
					in_previous_month_activity_list = True
			# If the log is not in the chart_list and it is in the span, add
			# it to the chart_list.
			if not in_previous_month_activity_list and log_time > 0:
				previous_month_activity_list.append([activity, log_time])
		# Search through the month_activity_list and
		# previous_month_activity_list for matching activities
		for activity in month_activity_list:
			for previous_activity in previous_month_activity_list:
				if activity[0] == previous_activity[0]:
					# Get the percent change between the two activities' times
					# as a string in the form of 100.00%
					percent_change = (((activity[1]-previous_activity[1])*1.00)
										/(previous_activity[1]*1.00))
					percent_change = str((ceil(percent_change*10000.00))/100.00)
					if percent_change[-2] == '.':
						percent_change += '0'
					percent_change += '%'
					# Add this activity and it's percent change to trends list
					trends.append([activity[0], percent_change])
		# Set data as trends
		self.data = trends

	def generate_span_trends(self, from_date, to_date):
		"""Takes logs from self.data and changes them to activity trends for
		since the previous day based on a given date tuple"""
		activity_list = []
		# Iterate through the log data.
		for log in self.data:
			# Get and format the information we need from the log.
			activity = log[0]
			log_start = unformat_time(tuple_time(log[1]))
			log_end = unformat_time(tuple_time(log[2]))
			minimum = unformat_time((0, 0, 0, from_date[0], from_date[1],
										from_date[2]))
			maximum = unformat_time((59, 59, 23, to_date[0], to_date[1],
										to_date[2]))
			log_time = time_in_span(log_start, log_end, minimum, maximum)
			# If the log exists in the span
			if log_time > 0:
				in_activity_list = False
				# Iterate through the activity list to check for duplicates
				for entry in activity_list:
					if entry[0] == activity:
						# Then the entry is in the activity list
						in_activity_list = True
						# Set the maximum of the span to check as the end of the
						# from_date
						maximum = unformat_time((59, 59, 23, from_date[0],
													from_date[1], from_date[2]))
						# If the log did not happen on the from date
						if not (time_in_span(log_start, log_end,
												minimum, maximum) == 0):
							# add the log's time in the span to the activity's
							# start trend time.
							entry[1] += time_in_span(log_start, log_end,
														minimum, maximum)
						else:
							# Else add it the activity's end trend time
							entry[2] += log_time
				# If the log is not already in the activity list, add it.
				if not in_activity_list:
					activity_list.append([activity, log_time, 0])
		# Make a list of the activities and their respective trends
		trends_list = []
		# Iterate through the activity list
		for entry in activity_list:
			# If the end trend time of the activity exists (I.E. not zero)
			if not entry[2] == 0:
				# Get the trend and convert it to a string with a percent symbol
				percent_change = (((entry[2] - entry[1])*1.00)/(entry[1]*1.00))
				percent_change = str((ceil(percent_change*10000.00))/100.00)
				if percent_change[-2] == '.':
					percent_change += '0'
				percent_change += '%'
				trends_list.append([entry[0], str(percent_change)])
		# Set data as trends
		self.data = trends_list

	def load_into_treeview_window(self):
		"""Load the treeviews data into the treestore widget"""
		for trend in self.data:
			# Get which pixbuf we will be using based on whether or not the
			# trend is positive.
			if float(trend[1][:-1]) > 0:
				pixbuf = self.up_pixbuf
			elif float(trend[1][:-1]) < 0:
				pixbuf = self.down_pixbuf
				trend[1] = trend[1][1:]
			else:
				pixbuf = self.same_pixbuf
			# append the data to the treestore
			self.treestore.append(None, (trend[0], pixbuf, trend[1]))

	def set_visible(self, visible=True):
		"""Used to make loading animation work correctly, need to remove"""
		self.treeview_window.set_visible(visible)
		self.visible = visible

	def clear(self):
		"""Clears the TrendView"""
		self.data = []
		self.treestore.clear()


from math import floor, ceil, exp
#selfig сюда мы вносим переменные в разных форматах числовое константное значения или функция или массив данных,
# после чего все это преобразуется в массив заданной длинны(в зависимости от delta_t) с точностью до 0,5 сек
#Time
class Config:
    t_mas = []
    Accuracy = []
    G = []
    #Rocket
    m_rocket = [] #in kg
    S_rocket = []
    Coefficient_resistance = []  # Коэффицент лобового сопротивления
    #Calculated
    distance = []
    a_rocket = []
    u_rocket = []
    #~Rocket

    #Fuel
    m_fuel = []
    u_fuel = []
    c_fuel = []
    #~Fuel

    #Planet
    M_planet = []
    R_planet = []
    Mol_gas = []
    #Calculated
    Temperature = [] #one string in mas (func (h))
    Atmospher_density = [] #Плотность атмосферы
    #~Planet
    R = 8.31445984848488

    #def
    def Normalization_config(self):
        t = self.t_mas[len(self.t_mas)-1]
        self.t_mas = [0]
        step = 1/self.Accuracy[0]
        i = 0
        while i < t * self.Accuracy[0]:
            self.t_mas.append(self.t_mas[i] + step)
            i += 1

        Var = [self.t_mas, self.m_rocket, self.a_rocket, self.u_rocket, self.S_rocket,
               self.u_fuel, self.m_fuel, self.c_fuel,
               self.distance,self.Atmospher_density, self.Mol_gas,
               self.Coefficient_resistance, self.Temperature]
        for x in Var:
            Temp = x[:]
            Repeat = [int(floor((t * self.Accuracy[0]) / len(x))), int(ceil((t * self.Accuracy[0]) / len(x)))]
            if Repeat[0] == 0:
                Repeat[0] = 1
            if Repeat[1] == 0:
                Repeat[1] = 1
            x.clear()
            for i in range(len(Temp)):
                for count in range(Repeat[i%2]):
                    if len(x) < t*self.Accuracy[0]:
                        x.append(Temp[i])

    def Calculate(self):
        delta_t = 1 / self.Accuracy[0]
        t = self.t_mas[len(self.t_mas) - 1] + self.Accuracy[0]
        F = self.G[0] * (self.m_fuel[0] + self.m_rocket[0]) * self.M_planet[0] \
            / ((self.R_planet[0] + self.distance[0]) ** 2)
        self.a_rocket[0] = (self.u_fuel[0] * self.c_fuel[0] * (self.m_fuel[0] != 0) - F) / (
        self.m_fuel[0] + self.m_rocket[0])
        self.Temperature[0] = max(1, self.Parse_Temperature(0))
        for i in range(1, int(self.Accuracy[0] * t)):
            F = 0
            self.distance[i] = self.distance[i - 1] + self.u_rocket[i - 1] * delta_t \
                               + self.a_rocket[i - 1] * delta_t ** 2 / 2
            self.u_rocket[i] = self.u_rocket[i - 1] + self.a_rocket[i - 1] * delta_t
            if (self.distance[i] < 0):
                self.distance[i] = 0
                self.u_rocket[i] = 0
            self.m_fuel[i] = self.m_fuel[i - 1] - self.c_fuel[i - 1] * delta_t
            if (self.m_fuel[i] < 0):
                self.m_fuel[i] = 0
            # Atmospher
            g = self.G[0]*self.M_planet[0]/(self.distance[i]+self.R_planet[0])**2
            #fixme
            self.Temperature[i] = max(1, self.Parse_Temperature(i))

            self.Atmospher_density[i] = self.Atmospher_density[i-1]* exp(-self.Mol_gas[i]*g*(self.distance[i] - self.distance[i-1])/(self.R*self.Temperature[i]))
            F += self.Coefficient_resistance[i] / 2 * self.Atmospher_density[i] * self.u_rocket[i] ** 2 * self.S_rocket[i]
            # ~Atmospher

            F = self.G[0] * (self.m_fuel[i] + self.m_rocket[i]) * self.M_planet[0] / (
            (self.R_planet[0] + self.distance[i]) ** 2)

            self.a_rocket[i] = (self.u_fuel[i] * self.c_fuel[i] * (self.m_fuel[i] != 0) - F) / (
            self.m_fuel[i] + self.m_rocket[i])
    def Parse_Temperature(self, i):
        from Parsers import eval_
        string = self.Temperature[i]
        string = string.replace('h', str(self.distance[i]))
        string = string.replace('H', str(self.distance[i]))
        string = eval_(string)
        return string


# -*- coding: utf-8 -*-
##!/usr/bin/python3

'''
sources of inspiration:
https://cseweb.ucsd.edu/~elkan/250Bwinter2011/mixturemodels.pdf
https://www.python-course.eu/expectation_maximization_and_gaussian_mixture_models.php
'''

import time
import numpy as np
from scipy.stats import norm
from matplotlib import pyplot as plt
from matplotlib import style

def gaussian_mix(sample_size, mu, sigma, weights):
    sample = np.empty((sample_size))
    for i in range(sample_size):
        Z = np.random.choice([0,1], p=weights) # latent variable
        sample[i] = (np.random.normal(mu[Z], sigma[Z], 1))
    return sample

class gaussian_mix_solver:
    def __init__(self, sample, max_iterations, tolerance):
        self.sample = sample
        self.max_iterations = max_iterations
        self.tolerance = tolerance
        # Start with arbitrary mu, sigma and weights
        self.mu = [0,0]
        self.sigma = [1,10]
        self.weights = [1/2,1/2]

        self.iter_mu = [self.mu]
        self.iter_sigma = [self.mu]
        self.iter_weights = [self.mu]

        self.log_likelihoods = []

    def run(self, plot):

        ### Plot initial ###
        if plot:
            fig = plt.figure(figsize=(10,10))
            ax0 = fig.add_subplot(111)
            """Plot the data"""
            for i in range(n):
                ax0.scatter(self.sample[i],0,s=100)
                #ax0.scatter(self.sample[i],0,c=np.array([membership[i][0],membership[i][1],membership[i][2]]),s=100)
            """Plot the gaussians"""
            for g,c in zip([norm(loc=self.mu[0],scale=self.sigma[0]).pdf(np.linspace(-20,20,num=n)),
                            norm(loc=self.mu[1],scale=self.sigma[1]).pdf(np.linspace(-20,20,num=n))],['r','b']):
                ax0.plot(np.linspace(-20,20,num=n),g,c=c)
            plt.title("estimation after 0 iterations:\n mu={},\n sigma={},\n weights={}".format(self.mu, self.sigma, self.weights))
            plt.show()

            print("\nEstimation at iteration no: 0")
            print(" mu= {}".format(self.mu))
            print(" sigma= {}".format(self.sigma))
            print(" weights= {}".format(self.weights))

        for iter in range(self.max_iterations):

            log_likelihood = np.log(np.sum([k*norm(self.mu[c],self.sigma[c]).pdf(self.sample) for k,c in zip(self.weights,range(2))]))
            self.log_likelihoods.append(log_likelihood)

            ### E-Step ###

            """Calculate probability for each datapoint x_i to belong to gaussian g"""
            membership = np.zeros((n,2))
            for column,g,weight in zip(range(2),
                                       [norm(loc=self.mu[0],scale=self.sigma[0]),
                                        norm(loc=self.mu[1],scale=self.sigma[1])],
                                       self.weights):
                # Write probability in column of membership
                membership[:,column] = weight*g.pdf(self.sample)
            """
            Now, Normalize the probabilities such that each row of membership sums to 1
            and weight it by mu_c == the fraction of points belonging to cluster c
            """
            for i in range(n):
                membership[i] = membership[i]/(np.sum(self.weights)*np.sum(membership,axis=1)[i])

            ### M-Step ###

            # For each cluster c, calculate the mean and add it to the list mean_c
            membership_cumulative = []
            for c in range(2):
                cumulative = np.sum(membership[:,c])
                membership_cumulative.append(cumulative)

            # For each cluster c, calculate the fraction of points which belongs to cluster c
            for c in range(2):
                fraction = membership_cumulative[c] / n
                self.weights[c] = fraction

            # calculate mu_c
            for c in range(2):
                mean  = np.sum(membership[:,c] * self.sample)
                mean /= membership_cumulative[c]
                self.mu[c] = mean

            # calculate var_c
            for c in range(2):
                var  = np.sum(membership[:,c] * np.power((self.sample-self.mu[c]), 2))
                var /= membership_cumulative[c]
                self.sigma[c] = np.sqrt(var)

            self.iter_mu.append(self.mu)
            self.iter_sigma.append(self.sigma)
            self.iter_weights.append(self.weights)

        best_iteration = np.argmax(self.log_likelihoods)
        self.max_mu = self.iter_mu[best_iteration]
        self.max_sigma = self.iter_sigma[best_iteration]
        self.max_weights = self.iter_weights[best_iteration]

        ### Plot final ###
        if plot:
            fig = plt.figure(figsize=(10,10))
            ax0 = fig.add_subplot(111)
            """Plot the data"""
            for i in range(n):
                ax0.scatter(self.sample[i],0,s=100)
                #ax0.scatter(self.sample[i],0,c=np.array([membership[i][0],membership[i][1],membership[i][2]]),s=100)
            """Plot the gaussians"""
            for g,c in zip([norm(loc=self.max_mu[0],scale=self.max_sigma[0]).pdf(np.linspace(-20,20,num=n)),
                            norm(loc=self.max_mu[1],scale=self.max_sigma[1]).pdf(np.linspace(-20,20,num=n))],['r','b']):
                ax0.plot(np.linspace(-20,20,num=n),g,c=c)
            plt.title("after {} iterations:\n mu={},\n sigma={},\n weights={}".format(iter, self.max_mu, self.max_sigma, self.max_weights))
            plt.show()

            print("\nBest result found at teration no: {}".format(best_iteration))
            print(" mu= {}".format(self.max_mu))
            print(" sigma= {}".format(self.max_sigma))
            print(" weights= {}".format(self.max_weights))

if __name__ == '__main__':

    n_samples = 5000
    n_samples = 500
    n = 250

    mu = 0
    var1 = 1
    var2 = 10

    max_iterations = 7
    tolerance = 0.0
    # real parameters for mixed gaussian
    real_mu = [0, 0]
    real_sigma = [1, np.sqrt(10)]
    real_weights = [.7, .3]

    print("---------------------------------------------------------------\n")
    print("            Uebung 4_5 David Blacher, Johannes Kurz            \n")
    print("---------------------------------------------------------------\n")
    print("Ziehe {}-mal Stichproben mit n={} aus Mischung "
          "von Normalverteilungen mit mu={}, var1={} & var2={}"
          .format(n_samples, n, mu,var1,var2))

    estimated_mu = np.empty((n_samples, 2))
    estimated_sigma = np.empty((n_samples, 2))
    estimated_weights = np.empty((n_samples, 2))

    for simulation in range(n_samples):
        entire_sample = gaussian_mix(n, real_mu, real_sigma, real_weights)
        gaussian_model = gaussian_mix_solver(entire_sample,max_iterations, tolerance)
        if simulation == 0:
            print("Beispielhaft wird eine numerische Berechnung grafisch sichtbar gemacht.")
            gaussian_model.run(True)

            plt.plot ( range(len(gaussian_model.log_likelihoods)), gaussian_model.log_likelihoods, label="priorA"  )
            plt.title("log likelyhood maximisation")
            plt.show()

            print("\nBitte geben Sie uns 10 sekunden für den Rest der Simulationen...")
        else:
            gaussian_model.run(False)

        estimated_mu[simulation] = gaussian_model.max_mu
        estimated_sigma[simulation] = gaussian_model.max_sigma
        estimated_weights[simulation] = gaussian_model.max_weights

    overall_mean_mu = np.sum(estimated_mu, axis=0) / n_samples
    overall_mean_sigma = np.sum(estimated_sigma, axis=0) / n_samples
    overall_mean_weights = np.sum(estimated_weights, axis=0) / n_samples

    print("\nNach {} Simulationen, sind dies die gemittelten Ergebnisse:".format(n_samples))
    print(" overall_mu= {}".format(overall_mean_mu))
    print(" overall_sigma= {}".format(overall_mean_sigma))
    print(" overall_weights= {}".format(overall_mean_weights))


import re

import boto.ec2

import ec2.metrics
import ec2.specs

def ec2_conn(env):
    return boto.ec2.connect_to_region(
        env['aws_ec2']['aws_region'],
        aws_access_key_id=env['aws_ec2']['aws_access_key'],
        aws_secret_access_key=env['aws_ec2']['aws_secret_key'])

def pull(env):
    """
    pulls interesting fields for all instances in the supplied envs from aws
    """
    interesting = [
        'id',
        'instance_type',
        'launch_time',
        'placement',
        'state',
        'tags',
        'virtualization_type',
        'vpc_id', ]

    instances = []
    conn = ec2_conn(env)
    for reservation in conn.get_all_instances():
        for instance in reservation.instances:
            data = {}
            for x in interesting:
                data[x] = getattr(instance, x)
            instances.append(data)
    return instances

def cook(instances):
    """
    takes a list of instances as retured by *pull* and normalizes the data to a
    useful form
    """
    vpcs = {}

    for instance in instances:
        vpc_id = instance['vpc_id']
        tags = instance['tags']
        if vpc_id and vpc_id not in vpcs:
            if 'Name' in tags:
                parts = tags['Name'].split('.')
                if len(parts) == 4:
                    vpcs[vpc_id] = parts[1]

    def env(instance):
        vpc_id = instance['vpc_id']
        tags = instance['tags']
        if vpc_id in vpcs:
            return vpcs[vpc_id]
        if 'Name' in tags:
            parts = tags['Name'].split('.')
            if len(parts) == 4:
                return parts[1]
        return 'unknown'

    def role(instance):
        tags = instance['tags']
        if 'role' in tags:
            return tags['role']
        if 'Name' in tags:
            prefix = tags['Name'].split('.')[0]
            match = re.match('^([a-z]*)\d', prefix)
            if match:
                return match.group(1)
        return 'unknown'

    columns = [
        ('role', lambda i: role(i)),
        ('env', lambda i: env(i)),
        ('host', lambda i: i['tags'].get('Name')),
        ('az', lambda i: i['placement']),
        ('type', lambda i: i['instance_type']),
        ('time', lambda i: i['launch_time']),
        ('virt', lambda i: i['virtualization_type']),
        ('state', None),
        ('id', None), ]

    cooked = []
    for instance in instances:
        row = {}
        for key, f in columns:
            f = f or (lambda i: instance[key])
            row[key] = f(instance)
        cooked.append(row)
    return cooked

#TODO THIS FUNCTION IS KINDA A BAD IDEA... IT SHOULD BE A PROGRAM ITSELF?
def get(envs, refresh=False):
    instances = []
    for env in envs:
        instances += pull(env)
    return cook(instances)

# lazy load and cache shared instance data
class DATA(object):
    def __init__(self):
        self._metrics = None
        self._specs = None

    @property
    def metrics(self):
        if not self._metrics:
            self._metrics = ec2.metrics.get()
        return self._metrics

    @property
    def specs(self):
        if not self._specs:
            self._specs = ec2.specs.get()
        return self._specs

DATA = DATA()

class Group(object):
    """
    represents a group of instances
    """
    def __init__(self, key):
        self.key = key
        self.instances = []

    def __getattr__(self, name):
        if name in self.instances[0]:
            return self.instances[0][name]
        raise AttributeError(name)

    def price(self, name, instance_type=None):
        prices = [
            DATA.specs[
                instance_type and instance_type or x['type']]['prices'][name]
            for x in self.instances]
        return sum(prices)

    def metric(self, name):
        members = [x[name] for x in self.metrics]
        if not members:
            return -1
        return sum(members) / len(members)

    @property
    def metrics(self):
        return [
            DATA.metrics[x['id']]
            for x in self.instances if x['id'] in DATA.metrics]

    @property
    def type(self):
        return list(set([x['type'] for x in self.instances]))

    @property
    def new(self):
        return bool([
            x for x in self.instances if x['virt'] == 'hvm'])

    def __len__(self):
        return len(self.instances)

    def __repr__(self):
        return 'Group(%s: %s)' % (self.key, len(self.instances))


import naivert
from Geometry3D import *
from math import sqrt

main_scene = naivert.Scene()

main_camera = naivert.Camera(Point(350,-250,350),Point(335,-235,335),10 * Vector(-1 /sqrt(6),1/sqrt(6),2/sqrt(6)),10*Vector(1/sqrt(2),1/sqrt(2),0),'main_camera.png',resolution=(600,600))
point_light2 = naivert.PointLight(Point(200,50,200),[4.0,4.0,4.0])
point_light = naivert.PointLight(Point(50,100,200),[5.0,5.0,5.0])
main_scene.add_camera(main_camera)
main_scene.add_light(point_light)
main_scene.add_light(point_light2)

main_scene.add_floor(-50,200,-50,200)

main_scene.add_cph(Sphere(Point(0,0,15),15,30,15),naivert.Material.DiffusionMaterial_White_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(100,0,15),15,30,15),naivert.Material.DiffusionMaterial_Green_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(100,100,15),15,30,15),naivert.Material.DiffusionMaterial_Red_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(0,100,15),15,30,15),naivert.Material.DiffusionMaterial_Blue_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(50,0,15),15,30,15),naivert.Material.SpecularMaterial_White_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(0,50,15),15,30,15),naivert.Material.SpecularMaterial_White_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(50,100,15),15,30,15),naivert.Material.SpecularMaterial_White_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(100,50,15),15,30,15),naivert.Material.SpecularMaterial_White_1(),reverse_normal=False)
main_scene.add_cph(Sphere(Point(50,50,15),15,30,15),naivert.Material.Glass(),reverse_normal=False)

# r = Renderer()
# for face in main_scene.face_list:
#     r.add((face.cpg,'r',1))
# r.show()
# print('begin')
main_scene.render_scene(56)

main_scene.write_scene()