text:
"""Routines for generating image plots.
"""
import colorsys
import locale
import time
try:
    from PIL import Image, ImageDraw
except ImportError:
    import Image, ImageDraw

import weeplot.utilities
import weeutil.weeutil
from weeutil.weeutil import to_unicode

# NB: All labels passed in should be in UTF-8. They are then converted to Unicode, which
# some fonts support, others don't. If the chosen font does not support Unicode, then the label
# will be changed back to UTF-8, then tried again.

class GeneralPlot(object):
    """Holds various parameters necessary for a plot. It should be specialized by the type of plot.

    """
    def __init__(self, config_dict):
        """Initialize an instance of GeneralPlot.

        config_dict: an instance of ConfigObj, or something that looks like it.

        """

        self.line_list = []

        self.xscale = None
        self.yscale = None

        self.anti_alias             = int(config_dict.get('anti_alias',  1))

        self.image_width            = int(config_dict.get('image_width',  300)) * self.anti_alias
        self.image_height           = int(config_dict.get('image_height', 180)) * self.anti_alias
        self.image_background_color = weeplot.utilities.tobgr(config_dict.get('image_background_color', '0xf5f5f5'))

        self.chart_background_color = weeplot.utilities.tobgr(config_dict.get('chart_background_color', '0xd8d8d8'))
        self.chart_gridline_color   = weeplot.utilities.tobgr(config_dict.get('chart_gridline_color',   '0xa0a0a0'))
        color_list                  = config_dict.get('chart_line_colors', ['0xff0000', '0x00ff00', '0x0000ff'])
        fill_color_list             = config_dict.get('chart_fill_colors', color_list)
        width_list                  = config_dict.get('chart_line_width',  [1, 1, 1])
        self.chart_line_colors      = [weeplot.utilities.tobgr(v) for v in color_list]
        self.chart_fill_colors      = [weeplot.utilities.tobgr(v) for v in fill_color_list]
        self.chart_line_widths      = [int(v) for v in width_list]

        self.top_label_font_path    = config_dict.get('top_label_font_path')
        self.top_label_font_size    = int(config_dict.get('top_label_font_size', 10)) * self.anti_alias

        self.unit_label             = None
        self.unit_label_font_path   = config_dict.get('unit_label_font_path')
        self.unit_label_font_color  = weeplot.utilities.tobgr(config_dict.get('unit_label_font_color', '0x000000'))
        self.unit_label_font_size   = int(config_dict.get('unit_label_font_size', 10)) * self.anti_alias
        self.unit_label_position    = (10, 0) * self.anti_alias

        self.bottom_label_font_path = config_dict.get('bottom_label_font_path')
        self.bottom_label_font_color= weeplot.utilities.tobgr(config_dict.get('bottom_label_font_color', '0x000000'))
        self.bottom_label_font_size = int(config_dict.get('bottom_label_font_size', 10)) * self.anti_alias
        self.bottom_label_offset    = int(config_dict.get('bottom_label_offset', 3))

        self.axis_label_font_path   = config_dict.get('axis_label_font_path')
        self.axis_label_font_color  = weeplot.utilities.tobgr(config_dict.get('axis_label_font_color', '0x000000'))
        self.axis_label_font_size   = int(config_dict.get('axis_label_font_size', 10)) * self.anti_alias

        self.x_label_format         = to_unicode(config_dict.get('x_label_format'))
        self.y_label_format         = to_unicode(config_dict.get('y_label_format'))

        # Calculate sensible margins for the given image and font sizes.
        self.lmargin = int(4.0 * self.axis_label_font_size)
        self.rmargin = 20 * self.anti_alias
        self.bmargin = int(1.5 * (self.bottom_label_font_size + self.axis_label_font_size) + 0.5)
        self.tmargin = int(1.5 * self.top_label_font_size + 0.5)
        self.tbandht = int(1.2 * self.top_label_font_size + 0.5)
        self.padding =  3 * self.anti_alias

        self.render_rose            = False
        self.rose_width             = int(config_dict.get('rose_width', 21))
        self.rose_height            = int(config_dict.get('rose_height', 21))
        self.rose_diameter          = int(config_dict.get('rose_diameter', 10))
        self.rose_position          = (self.lmargin + self.padding + 5, self.image_height - self.bmargin - self.padding - self.rose_height)
        self.rose_rotation          = None
        self.rose_label             = to_unicode(config_dict.get('rose_label', 'N'))
        self.rose_label_font_path   = config_dict.get('rose_label_font_path', self.bottom_label_font_path)
        self.rose_label_font_size   = int(config_dict.get('rose_label_font_size', 10))
        self.rose_label_font_color  = weeplot.utilities.tobgr(config_dict.get('rose_label_font_color', '0x000000'))
        self.rose_color             = config_dict.get('rose_color')
        if self.rose_color is not None:
            self.rose_color = weeplot.utilities.tobgr(self.rose_color)

        # Show day/night transitions
        self.show_daynight          = weeutil.weeutil.tobool(config_dict.get('show_daynight', False))
        self.daynight_day_color     = weeplot.utilities.tobgr(config_dict.get('daynight_day_color', '0xffffff'))
        self.daynight_night_color   = weeplot.utilities.tobgr(config_dict.get('daynight_night_color', '0xf0f0f0'))
        self.daynight_edge_color    = weeplot.utilities.tobgr(config_dict.get('daynight_edge_color', '0xefefef'))
        self.daynight_gradient      = int(config_dict.get('daynight_gradient', 20))

    def setBottomLabel(self, bottom_label):
        """Set the label to be put at the bottom of the plot.

        """
        self.bottom_label = to_unicode(bottom_label)

    def setUnitLabel(self, unit_label):
        """Set the label to be used to show the units of the plot.

        """
        self.unit_label = to_unicode(unit_label)

    def setXScaling(self, xscale):
        """Set the X scaling.

        xscale: A 3-way tuple (xmin, xmax, xinc)
        """
        self.xscale = xscale

    def setYScaling(self, yscale):
        """Set the Y scaling.

        yscale: A 3-way tuple (ymin, ymax, yinc)
        """
        self.yscale = yscale

    def addLine(self, line):
        """Add a line to be plotted.

        line: an instance of PlotLine

        """
        if None in line.x:
            raise weeplot.ViolatedPrecondition, "X vector cannot have any values 'None' "
        self.line_list.append(line)

    def setLocation(self, lat, lon):
        self.latitude  = lat
        self.longitude = lon

    def setDayNight(self, showdaynight, daycolor, nightcolor, edgecolor):
        """Configure day/night bands.

        showdaynight: Boolean flag indicating whether to draw day/night bands

        daycolor: color for day bands

        nightcolor: color for night bands

        edgecolor: color for transition between day and night
        """
        self.show_daynight = showdaynight
        self.daynight_day_color = daycolor
        self.daynight_night_color = nightcolor
        self.daynight_edge_color = edgecolor

    def render(self):
        """Traverses the universe of things that have to be plotted in this image, rendering
        them and returning the results as a new Image object.

        """

        # NB: In what follows the variable 'draw' is an instance of an ImageDraw object and is in pixel units.
        # The variable 'sdraw' is an instance of ScaledDraw and its units are in the "scaled" units of the plot
        # (e.g., the horizontal scaling might be for seconds, the vertical for degrees Fahrenheit.)
        image = Image.new("RGB", (self.image_width, self.image_height), self.image_background_color)
        draw = self._getImageDraw(image)
        draw.rectangle(((self.lmargin,self.tmargin),
                        (self.image_width - self.rmargin, self.image_height - self.bmargin)),
                        fill=self.chart_background_color)

        self._renderBottom(draw)
        self._renderTopBand(draw)

        self._calcXScaling()
        self._calcYScaling()
        self._calcXLabelFormat()
        self._calcYLabelFormat()

        sdraw = self._getScaledDraw(draw)
        if self.show_daynight:
            self._renderDayNight(sdraw)
        self._renderXAxes(sdraw)
        self._renderYAxes(sdraw)
        self._renderPlotLines(sdraw)
        if self.render_rose:
            self._renderRose(image, draw)

        if self.anti_alias != 1:
            image.thumbnail((self.image_width / self.anti_alias, self.image_height / self.anti_alias), Image.ANTIALIAS)

        return image

    def _getImageDraw(self, image):
        """Returns an instance of ImageDraw with the proper dimensions and background color"""
        draw = UniDraw(image)
        return draw

    def _getScaledDraw(self, draw):
        """Returns an instance of ScaledDraw, with the appropriate scaling.

        draw: An instance of ImageDraw
        """
        sdraw = weeplot.utilities.ScaledDraw(draw, ((self.lmargin + self.padding, self.tmargin + self.padding),
                                                    (self.image_width - self.rmargin - self.padding, self.image_height - self.bmargin - self.padding)),
                                                    ((self.xscale[0], self.yscale[0]), (self.xscale[1], self.yscale[1])))
        return sdraw

    def _renderDayNight(self, sdraw):
        """Draw vertical bands for day/night."""
        (first, transitions) = weeutil.weeutil.getDayNightTransitions(
            self.xscale[0], self.xscale[1], self.latitude, self.longitude)
        color = self.daynight_day_color \
            if first == 'day' else self.daynight_night_color
        xleft = self.xscale[0]
        for x in transitions:
            sdraw.rectangle(((xleft,self.yscale[0]),
                             (x,self.yscale[1])), fill=color)
            xleft = x
            color = self.daynight_night_color \
                if color == self.daynight_day_color else self.daynight_day_color
        sdraw.rectangle(((xleft,self.yscale[0]),
                         (self.xscale[1],self.yscale[1])), fill=color)
        if self.daynight_gradient:
            if first == 'day':
                color1 = self.daynight_day_color
                color2 = self.daynight_night_color
            else:
                color1 = self.daynight_night_color
                color2 = self.daynight_day_color
            nfade = self.daynight_gradient
            # gradient is longer at the poles than the equator
            d = 120 + 300 * (1 - (90.0 - abs(self.latitude)) / 90.0)
            for i in range(len(transitions)):
                last_ = self.xscale[0] if i == 0 else transitions[i-1]
                next_ = transitions[i+1] if i < len(transitions)-1 else self.xscale[1]
                for z in range(1,nfade):
                    c = blend_hls(color2, color1, float(z)/float(nfade))
                    rgbc = int2rgbstr(c)
                    x1 = transitions[i]-d*(nfade+1)/2+d*z
                    if last_ < x1 < next_:
                        sdraw.rectangle(((x1, self.yscale[0]),
                                         (x1+d, self.yscale[1])),
                                        fill=rgbc)
                if color1 == self.daynight_day_color:
                    color1 = self.daynight_night_color
                    color2 = self.daynight_day_color
                else:
                    color1 = self.daynight_day_color
                    color2 = self.daynight_night_color
        # draw a line at the actual sunrise/sunset
        for x in transitions:
            sdraw.line((x,x),(self.yscale[0],self.yscale[1]),
                       fill=self.daynight_edge_color)

    def _renderXAxes(self, sdraw):
        """Draws the x axis and vertical constant-x lines, as well as the labels.

        """

        axis_label_font = weeplot.utilities.get_font_handle(self.axis_label_font_path,
                                                            self.axis_label_font_size)

        drawlabel = False
        for x in weeutil.weeutil.stampgen(self.xscale[0], self.xscale[1], self.xscale[2]) :
            sdraw.line((x, x), (self.yscale[0], self.yscale[1]), fill=self.chart_gridline_color,
                       width=self.anti_alias)
            drawlabel = not drawlabel
            if drawlabel:
                xlabel = self._genXLabel(x)
                axis_label_size = sdraw.draw.textsize(xlabel, font=axis_label_font)
                xpos = sdraw.xtranslate(x)
                sdraw.draw.text((xpos - axis_label_size[0]/2, self.image_height - self.bmargin + 2),
                                xlabel, fill=self.axis_label_font_color, font=axis_label_font)

    def _renderYAxes(self, sdraw):
        """Draws the y axis and horizontal constant-y lines, as well as the labels.
        Should be sufficient for most purposes.

        """
        nygridlines     = int((self.yscale[1] - self.yscale[0]) / self.yscale[2] + 1.5)
        axis_label_font = weeplot.utilities.get_font_handle(self.axis_label_font_path,
                                                                self.axis_label_font_size)

        # Draw the (constant y) grid lines
        for i in xrange(nygridlines) :
            y = self.yscale[0] + i * self.yscale[2]
            sdraw.line((self.xscale[0], self.xscale[1]), (y, y), fill=self.chart_gridline_color,
                       width=self.anti_alias)
            # Draw a label on every other line:
            if i%2 == 0 :
                ylabel = self._genYLabel(y)
                axis_label_size = sdraw.draw.textsize(ylabel, font=axis_label_font)
                ypos = sdraw.ytranslate(y)
                sdraw.draw.text((self.lmargin - axis_label_size[0] - 2, ypos - axis_label_size[1]/2),
                                ylabel, fill=self.axis_label_font_color, font=axis_label_font)

    def _renderPlotLines(self, sdraw):
        """Draw the collection of lines, using a different color for each one. Because there is
        a limited set of colors, they need to be recycled if there are very many lines.

        """
        nlines = len(self.line_list)
        ncolors = len(self.chart_line_colors)
        nfcolors = len(self.chart_fill_colors)
        nwidths = len(self.chart_line_widths)

        # Draw them in reverse order, so the first line comes out on top of the image
        for j, this_line in enumerate(self.line_list[::-1]):

            iline=nlines-j-1
            color = self.chart_line_colors[iline%ncolors] if this_line.color is None else this_line.color
            fill_color = self.chart_fill_colors[iline%nfcolors] if this_line.fill_color is None else this_line.fill_color
            width = (self.chart_line_widths[iline%nwidths] if this_line.width is None else this_line.width) * self.anti_alias

            # Calculate the size of a gap in data
            maxdx = None
            if this_line.gap_fraction is not None:
                maxdx = this_line.gap_fraction * (self.xscale[1] - self.xscale[0])

            if this_line.plot_type == 'line' :
                ms = this_line.marker_size
                if ms is not None:
                    ms *= self.anti_alias
                sdraw.line(this_line.x,
                           this_line.y,
                           line_type=this_line.line_type,
                           marker_type=this_line.marker_type,
                           marker_size=ms,
                           fill  = color,
                           width = width,
                           maxdx = maxdx)
            elif this_line.plot_type == 'bar' :
                for x, y, bar_width in zip(this_line.x, this_line.y, this_line.bar_width):
                    if y is None:
                        continue
                    sdraw.rectangle(((x - bar_width, self.yscale[0]), (x, y)), fill=fill_color, outline=color)
            elif this_line.plot_type == 'vector' :
                for (x, vec) in zip(this_line.x, this_line.y):
                    sdraw.vector(x, vec,
                                 vector_rotate = this_line.vector_rotate,
                                 fill  = color,
                                 width = width)
                self.render_rose = True
                self.rose_rotation = this_line.vector_rotate
                if self.rose_color is None:
                    self.rose_color = color

    def _renderBottom(self, draw):
        """Draw anything at the bottom (just some text right now).

        """
        bottom_label_font = weeplot.utilities.get_font_handle(self.bottom_label_font_path, self.bottom_label_font_size)
        bottom_label_size = draw.textsize(self.bottom_label, font=bottom_label_font)

        draw.text(((self.image_width - bottom_label_size[0])/2,
                   self.image_height - bottom_label_size[1] - self.bottom_label_offset),
                  self.bottom_label,
                  fill=self.bottom_label_font_color,
                  font=bottom_label_font)

    def _renderTopBand(self, draw):
        """Draw the top band and any text in it.

        """
        # Draw the top band rectangle
        draw.rectangle(((0,0),
                        (self.image_width, self.tbandht)),
                        fill = self.chart_background_color)

        # Put the units in the upper left corner
        unit_label_font = weeplot.utilities.get_font_handle(self.unit_label_font_path, self.unit_label_font_size)
        if self.unit_label:
            draw.text(self.unit_label_position,
                      self.unit_label,
                      fill=self.unit_label_font_color,
                      font=unit_label_font)

        top_label_font = weeplot.utilities.get_font_handle(self.top_label_font_path, self.top_label_font_size)

        # The top label is the appended label_list. However, it has to be drawn in segments
        # because each label may be in a different color. For now, append them together to get
        # the total width
        top_label = ' '.join([line.label for line in self.line_list])
        top_label_size = draw.textsize(top_label, font=top_label_font)

        x = (self.image_width - top_label_size[0])/2
        y = 0

        ncolors = len(self.chart_line_colors)
        for i, this_line in enumerate(self.line_list):
            color = self.chart_line_colors[i%ncolors] if this_line.color is None else this_line.color
            # Draw a label
            draw.text( (x,y), this_line.label, fill = color, font = top_label_font)
            # Now advance the width of the label we just drew, plus a space:
            label_size = draw.textsize(this_line.label + ' ', font= top_label_font)
            x += label_size[0]

    def _renderRose(self, image, draw):
        """Draw a compass rose."""

        rose_center_x = self.rose_width/2  + 1
        rose_center_y = self.rose_height/2 + 1
        barb_width  = 3
        barb_height = 3
        # The background is all white with a zero alpha (totally transparent)
        rose_image = Image.new("RGBA", (self.rose_width, self.rose_height), (0x00, 0x00, 0x00, 0x00))
        rose_draw = ImageDraw.Draw(rose_image)

        fill_color = add_alpha(self.rose_color)
        # Draw the arrow straight up (North). First the shaft:
        rose_draw.line( ((rose_center_x, 0), (rose_center_x, self.rose_height)), width = 1, fill = fill_color)
        # Now the left barb:
        rose_draw.line( ((rose_center_x - barb_width, barb_height), (rose_center_x, 0)), width = 1, fill = fill_color)
        # And the right barb:
        rose_draw.line( ((rose_center_x, 0), (rose_center_x + barb_width, barb_height)), width = 1, fill = fill_color)

        rose_draw.ellipse(((rose_center_x - self.rose_diameter/2,
                            rose_center_y - self.rose_diameter/2),
                           (rose_center_x + self.rose_diameter/2,
                            rose_center_y + self.rose_diameter/2)),
                          outline = fill_color)

        # Rotate if necessary:
        if self.rose_rotation:
            rose_image = rose_image.rotate(self.rose_rotation)
            rose_draw = ImageDraw.Draw(rose_image)

        # Calculate the position of the "N" label:
        rose_label_font = weeplot.utilities.get_font_handle(self.rose_label_font_path, self.rose_label_font_size)
        rose_label_size = draw.textsize(self.rose_label, font=rose_label_font)

        # Draw the label in the middle of the (possibly) rotated arrow
        rose_draw.text((rose_center_x - rose_label_size[0]/2 - 1,
                        rose_center_y - rose_label_size[1]/2 - 1),
                        self.rose_label,
                        fill = add_alpha(self.rose_label_font_color),
                        font = rose_label_font)

        # Paste the image of the arrow on to the main plot. The alpha
        # channel of the image will be used as the mask.
        # This will cause the arrow to overlay the background plot
        image.paste(rose_image, self.rose_position, rose_image)

    def _calcXScaling(self):
        """Calculates the x scaling. It will probably be specialized by
        plots where the x-axis represents time.

        """
        if self.xscale is None :
            (xmin, xmax) = self._calcXMinMax()

            self.xscale = weeplot.utilities.scale(xmin, xmax)

    def _calcYScaling(self):
        """Calculates y scaling. Can be used 'as-is' for most purposes."""
        # The filter is necessary because unfortunately the value 'None' is not
        # excluded from min and max (i.e., min(None, x) is not necessarily x).
        # The try block is necessary because min of an empty list throws a
        # ValueError exception.
        ymin = ymax = None
        for line in self.line_list:
            if line.plot_type == 'vector':
                try:
                    yline_max = max(abs(c) for c in filter(lambda v : v is not None, line.y))
                except ValueError:
                    yline_max = None
                yline_min = - yline_max if yline_max is not None else None
            else:
                yline_min = weeutil.weeutil.min_with_none(line.y)
                yline_max = weeutil.weeutil.max_with_none(line.y)
            ymin = weeutil.weeutil.min_with_none([ymin, yline_min])
            ymax = weeutil.weeutil.max_with_none([ymax, yline_max])

        if ymin is None and ymax is None :
            # No valid data. Pick an arbitrary scaling
            self.yscale=(0.0, 1.0, 0.2)
        else:
            self.yscale = weeplot.utilities.scale(ymin, ymax, self.yscale)

    def _calcXLabelFormat(self):
        if self.x_label_format is None:
            self.x_label_format = weeplot.utilities.pickLabelFormat(self.xscale[2])

    def _calcYLabelFormat(self):
        if self.y_label_format is None:
            self.y_label_format = weeplot.utilities.pickLabelFormat(self.yscale[2])

    def _genXLabel(self, x):
        xlabel = locale.format(self.x_label_format, x)
        return xlabel

    def _genYLabel(self, y):
        ylabel = locale.format(self.y_label_format, y)
        return ylabel

    def _calcXMinMax(self):
        xmin = xmax = None
        for line in self.line_list:
            xline_min = weeutil.weeutil.min_with_none(line.x)
            xline_max = weeutil.weeutil.max_with_none(line.x)
            # If the line represents a bar chart, then the actual minimum has to
            # be adjusted for the bar width of the first point
            if line.plot_type == 'bar':
                xline_min = xline_min - line.bar_width[0]
            xmin = weeutil.weeutil.min_with_none([xmin, xline_min])
            xmax = weeutil.weeutil.max_with_none([xmax, xline_max])
        return (xmin, xmax)

class TimePlot(GeneralPlot) :
    """Class that specializes GeneralPlot for plots where the x-axis is time."""

    def _calcXScaling(self):
        """Specialized version for time plots."""
        if self.xscale is None :
            (xmin, xmax) = self._calcXMinMax()
            self.xscale = weeplot.utilities.scaletime(xmin, xmax)

    def _calcXLabelFormat(self):
        """Specialized version for time plots."""
        if self.x_label_format is None:
            (xmin, xmax) = self._calcXMinMax()
            if xmin is not None and xmax is not None:
                delta = xmax - xmin
                if delta > 30*24*3600:
                    self.x_label_format = u"%x"
                elif delta > 24*3600:
                    self.x_label_format = u"%x %X"
                else:
                    self.x_label_format = u"%X"

    def _genXLabel(self, x):
        if self.x_label_format is None:
            return ''
        time_tuple = time.localtime(x)
        # The function time.strftime() still does not support Unicode, so we have to explicitly
        # convert it to UTF8, then back again:
        xlabel = to_unicode(time.strftime(self.x_label_format.encode('utf8'), time_tuple))
        return xlabel

class PlotLine(object):
    """Represents a single line (or bar) in a plot.

    """
    def __init__(self, x, y, label='', color=None, width=None, plot_type='line',
                 line_type='solid', marker_type=None, marker_size=10,
                 bar_width=None, vector_rotate = None, gap_fraction=None):
        self.x           = x
        self.y           = y
        self.label       = to_unicode(label)
        self.plot_type   = plot_type
        self.line_type   = line_type
        self.marker_type = marker_type
        self.marker_size = marker_size
        self.color       = color
        self.fill_color  = color
        self.width       = width
        self.bar_width   = bar_width
        self.vector_rotate = vector_rotate
        self.gap_fraction = gap_fraction

class UniDraw(ImageDraw.ImageDraw):
    """Supports non-Unicode fonts

    Not all fonts support Unicode characters. These will raise a UnicodeEncodeError exception.
    This class subclasses the regular ImageDraw.Draw class, adding overridden functions to
    catch these exceptions. It then tries drawing the string again, this time as a UTF8 string"""

    def text(self, position, string, **options):
        try:
            return ImageDraw.ImageDraw.text(self, position, string, **options)
        except UnicodeEncodeError:
            return ImageDraw.ImageDraw.text(self, position, string.encode('utf8'), **options)

    def textsize(self, string, **options):
        try:
            return ImageDraw.ImageDraw.textsize(self, string, **options)
        except UnicodeEncodeError:
            return ImageDraw.ImageDraw.textsize(self, string.encode('utf8'), **options)

def blend_hls(c, bg, alpha):
    """Fade from c to bg using alpha channel where 1 is solid and 0 is
    transparent.  This fades across the hue, saturation, and lightness."""
    return blend(c, bg, alpha, alpha, alpha)

def blend_ls(c, bg, alpha):
    """Fade from c to bg where 1 is solid and 0 is transparent.
    Change only the lightness and saturation, not hue."""
    return blend(c, bg, 1.0, alpha, alpha)

def blend(c, bg, alpha_h, alpha_l, alpha_s):
    """Fade from c to bg in the hue, lightness, saturation colorspace."""
    r1,g1,b1 = int2rgb(c)
    h1,l1,s1 = colorsys.rgb_to_hls(r1/256.0, g1/256.0, b1/256.0)
    r2,g2,b2 = int2rgb(bg)
    h2,l2,s2 = colorsys.rgb_to_hls(r2/256.0, g2/256.0, b2/256.0)
    h = alpha_h * h1 + (1 - alpha_h) * h2
    l = alpha_l * l1 + (1 - alpha_l) * l2
    s = alpha_s * s1 + (1 - alpha_s) * s2
    r,g,b = colorsys.hls_to_rgb(h, l, s)
    r = round(r * 256.0)
    g = round(g * 256.0)
    b = round(b * 256.0)
    t = rgb2int(int(r),int(g),int(b))
    return int(t)

def int2rgb(x):
    b = (x >> 16) & 0xff
    g = (x >> 8) & 0xff
    r = x & 0xff
    return r,g,b

def int2rgbstr(x):
    return '#%02x%02x%02x' % int2rgb(x)

def rgb2int(r,g,b):
    return r + g*256 + b*256*256

def add_alpha(i):
    """Add an opaque alpha channel to an integer RGB value"""
    r = i & 0xff
    g = (i >> 8)  & 0xff
    b = (i >> 16) & 0xff
    a = 0xff    # Opaque alpha
    return (r,g,b,a)


text:
* support geo_taxonomy

### 0.9.0 (2022-07-01)

#### Features

* Updated minimum Ruby version to 2.6 ([#18443](https://github.com/googleapis/google-cloud-ruby/issues/18443))

### 0.8.0 (2022-04-20)

#### Features

* Support for update masks when setting IAM policies

### 0.7.5 / 2022-01-11

#### Documentation

* Fix titles of documentation pages
* Remove some broken images and fix outdated content in authentication documentation

### 0.7.4 / 2021-11-08

#### Documentation

* Added simple code snippets to RPC method documentation

### 0.7.3 / 2021-08-11

#### Bug Fixes

* Honor client-level timeout configuration

### 0.7.2 / 2021-07-12

#### Documentation

* Clarify some language around authentication configuration

### 0.7.1 / 2021-06-17

#### Bug Fixes

* Support future 1.x versions of gapic-common

### 0.7.0 / 2021-03-08

#### Features

* Drop support for Ruby 2.4 and add support for Ruby 3.0

### 0.6.0 / 2021-02-02

#### Features

* Use self-signed JWT credentials when possible

### 0.5.6 / 2021-01-19

#### Documentation

* Timeout config description correctly gives the units as seconds.

### 0.5.5 / 2020-08-10

#### Bug Fixes

* Allow special symbolic credentials in client configs

### 0.5.4 / 2020-08-06

#### Bug Fixes

* Fix retry logic by checking the correct numeric error codes

### 0.5.3 / 2020-06-18

#### Documentation

* Add documentation and API enablement links to the readme

### 0.5.2 / 2020-06-05

#### Bug Fixes

* Eliminate a Ruby warning that appeared in some cases when accessing rpc-scoped configs

### 0.5.1 / 2020-05-26

#### Bug Fixes

* Removed unused google/cloud/common_resources_pb file

### 0.5.0 / 2020-05-20

#### Features

* The quota_project can be set via configuration

### 0.4.1 / 2020-05-05

#### Documentation

* Clarify that timeouts are in seconds.

### 0.4.0 / 2020-04-13

#### Features

* Support additional IAM features, and other updates.
  * Added support for IAM policy options.
  * Added support for IAM policy binding conditions.
  * Added support for IAM audit config deltas.
  * Expanded the readme to include quickstart and logging information.
  * Added documentation for package and service modules.
  * Fixed and expanded documentation for the two method calling conventions.
  * Fixed some circular require warnings.

### 0.3.1 / 2020-04-01

#### Documentation

* Update documentation for core proto types.

### 0.3.0 / 2020-03-25

#### Features

* Path helpers can be called as module functions

#### Documentation

* Expansion and cleanup of service description text

### 0.2.0 / 2020-03-18

* Support separate project setting for quota/billing
* Include the correct default timeout and retry settings
* Eliminate some Ruby 2.7 keyword argument warnings
* Add Configuration docs and update enum return types
* Fix various formatting issues in inline documentation

### 0.1.1 / 2020-02-24

#### Documentation

* Update homepage in README and gemspec

### 0.1.0 / 2020-02-09

* Initial release

redpajama_set_name: RedPajamaGithub


text:
'use strict';

var myApp = angular.module('myApp.controllers', []);

myApp.controller('ReportsIndexCtrl', [ '$scope', 'Report', function($scope, Report) {
  $scope.reports = Report.list();

}]);

myApp.controller('ReportsShowCtrl', [ '$scope', 'Report', '$routeParams', 'Meta', 'PathHelper', function(
                                       $scope,   Report,   $routeParams,   Meta,   PathHelper) {
  $scope.Meta = Meta;
  $scope.report = Report.get({ name_seo: $routeParams.name_seo }, function(r, headers) {
    $scope.Meta.setTitle( $scope.report.name );
    $scope.Meta.setDescription( $scope.report.subtitle || $scope.report.descr.substr(0,200) );
    $scope.Meta.setKeywords( $scope.report.name );
  });

}]);


text:
<?php namespace App\Http\Controllers;

use App\Http\Requests;
use App\Services\Verify\Verify;

class UGCController extends Controller {

	/**
	 * Display a listing of the resource.
	 *
	 * @return Response
	 */
	public function index()
	{
		//
	}

	/**
	 * Show the form for creating a new resource.
	 *
	 * @return Response
	 */
	public function create()
	{
        $ourTeamURL = 'http://www.ugcleague.com/team_page.cfm?clan_id=8838';
        $theirTeamURL = 'http://www.ugcleague.com/team_page.cfm?clan_id=9831';
        $sampleStatus = 'Type \'status\' into your in-game console and paste results here';

        $popoverTitle = "UGC Roster Verifier";
        $popoverText = "
This tool allows you to conveniently verify every TF2 player on the
server as long as you have both team's UGC profile URL and the Valve server
status outputs.

This app saves 90% of your time prior to the match for 100% roster verification accuracy.

I am always improving this service, so feel free to send me feedback!
";

		return view(
            'verify.verify',
            compact(
                'ourTeamURL',
                'theirTeamURL',
                'sampleStatus',
                'popoverTitle',
                'popoverText'
        ));
	}

    /**
     * Display the results of UGC verification
     * @param Requests\VerifyUGCRequest $request
     * @return \Illuminate\View\View
     */
    public function verify(Requests\VerifyUGCRequest $request)
    {
        $ourTeamURL = $request->input('our_team_link');
        $theirTeamURL = $request->input('their_team_link');
        $status = $request->input('status_text');

        $verify = new Verify($ourTeamURL, $theirTeamURL, $status);

        $ourRosterName = $verify->getOurRosterName();
        $ourRosterSize = $verify->getOurRosterSize();
        $ourRosterURL = $verify->getOurRosterURL();
        $ourTeamProfile = $verify->getOurTeamProfile();
        $ourTeamRanks = $verify->getOurTeamRanks();
        $ourTeamUGC = $verify->getOurTeamUGC();

        $theirRosterName = $verify->getTheirRosterName();
        $theirRosterSize = $verify->getTheirRosterSize();
        $theirRosterURL = $verify->getTheirRosterURL();
        $theirTeamProfile = $verify->getTheirTeamProfile();
        $theirTeamRanks = $verify->getTheirTeamRanks();
        $theirTeamUGC = $verify->getTheirTeamUGC();

        $unrostered = $verify->getUnrosteredProfile();
        $unrosteredNumber = $verify->getUnrosteredSize();
        $unrosteredRanks = $verify->getUnrosteredRanks();
        $unrosteredUGC = $verify->getUnrosteredUGC();

        return view(
            'verify.verify_results',
            compact(
                'ourRosterName',
                'ourRosterSize',
                'ourRosterURL',
                'ourTeamProfile',
                'theirRosterName',
                'theirRosterSize',
                'theirRosterURL',
                'theirTeamProfile',
                'unrostered',
                'unrosteredNumber',
                'ourTeamRanks',
                'theirTeamRanks',
                'unrosteredRanks',
                'ourTeamUGC',
                'theirTeamUGC',
                'unrosteredUGC'
            )
        );
    }

	/**
	 * Store a newly created resource in storage.
	 *
	 * @return Response
	 */
	public function store()
	{
		//
	}

	/**
	 * Display the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function show($id)
	{
		//
	}

	/**
	 * Show the form for editing the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function edit($id)
	{
		//
	}

	/**
	 * Update the specified resource in storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function update($id)
	{
		//
	}

	/**
	 * Remove the specified resource from storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function destroy($id)
	{
		//
	}

}


text:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="vendor/autoload.php">
  <coverage processUncoveredFiles="true">
    <report>
      <clover outputFile="build/logs/clover.xml"/>
    </report>
    <include>
      <directory suffix=".php">src</directory>
    </include>
  </coverage>
  <testsuites>
    <testsuite name="default">
      <directory suffix="Test.php">tests</directory>
    </testsuite>
  </testsuites>
</phpunit>


text:
This folder contains the following guides:

1.  [Developing End To End Tests](./developing-end-to-end-tests.md): A guide that describes how we write and run end to end (E2E) tests locally.
2.  [Learning Resources for our Dependencies](./dependency-learning-resources.md): A compendium of resources that can be used to familiarize yourself with our dependencies.


text:
using namespace llvm;
using namespace consthoist;

#define DEBUG_TYPE "consthoist"

STATISTIC(NumConstantsHoisted, "Number of constants hoisted");
STATISTIC(NumConstantsRebased, "Number of constants rebased");

static cl::opt<bool> ConstHoistWithBlockFrequency(
    "consthoist-with-block-frequency", cl::init(true), cl::Hidden,
    cl::desc("Enable the use of the block frequency analysis to reduce the "
             "chance to execute const materialization more frequently than "
             "without hoisting."));

namespace {

/// The constant hoisting pass.
class ConstantHoistingLegacyPass : public FunctionPass {
public:
  static char ID; // Pass identification, replacement for typeid

  ConstantHoistingLegacyPass() : FunctionPass(ID) {
    initializeConstantHoistingLegacyPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnFunction(Function &Fn) override;

  StringRef getPassName() const override { return "Constant Hoisting"; }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    if (ConstHoistWithBlockFrequency)
      AU.addRequired<BlockFrequencyInfoWrapperPass>();
    AU.addRequired<DominatorTreeWrapperPass>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
  }

  void releaseMemory() override { Impl.releaseMemory(); }

private:
  ConstantHoistingPass Impl;
};

} // end anonymous namespace

char ConstantHoistingLegacyPass::ID = 0;

INITIALIZE_PASS_BEGIN(ConstantHoistingLegacyPass, "consthoist",
                      "Constant Hoisting", false, false)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_END(ConstantHoistingLegacyPass, "consthoist",
                    "Constant Hoisting", false, false)

FunctionPass *llvm::createConstantHoistingPass() {
  return new ConstantHoistingLegacyPass();
}

/// Perform the constant hoisting optimization for the given function.
bool ConstantHoistingLegacyPass::runOnFunction(Function &Fn) {
  if (skipFunction(Fn))
    return false;

  LLVM_DEBUG(dbgs() << "********** Begin Constant Hoisting **********\n");
  LLVM_DEBUG(dbgs() << "********** Function: " << Fn.getName() << '\n');

  bool MadeChange =
      Impl.runImpl(Fn, getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn),
                   getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
                   ConstHoistWithBlockFrequency
                       ? &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI()
                       : nullptr,
                   Fn.getEntryBlock());

  if (MadeChange) {
    LLVM_DEBUG(dbgs() << "********** Function after Constant Hoisting: "
                      << Fn.getName() << '\n');
    LLVM_DEBUG(dbgs() << Fn);
  }
  LLVM_DEBUG(dbgs() << "********** End Constant Hoisting **********\n");

  return MadeChange;
}

/// Find the constant materialization insertion point.
Instruction *ConstantHoistingPass::findMatInsertPt(Instruction *Inst,
                                                   unsigned Idx) const {
  // If the operand is a cast instruction, then we have to materialize the
  // constant before the cast instruction.
  if (Idx != ~0U) {
    Value *Opnd = Inst->getOperand(Idx);
    if (auto CastInst = dyn_cast<Instruction>(Opnd))
      if (CastInst->isCast())
        return CastInst;
  }

  // The simple and common case. This also includes constant expressions.
  if (!isa<PHINode>(Inst) && !Inst->isEHPad())
    return Inst;

  // We can't insert directly before a phi node or an eh pad. Insert before
  // the terminator of the incoming or dominating block.
  assert(Entry != Inst->getParent() && "PHI or landing pad in entry block!");
  if (Idx != ~0U && isa<PHINode>(Inst))
    return cast<PHINode>(Inst)->getIncomingBlock(Idx)->getTerminator();

  // This must be an EH pad. Iterate over immediate dominators until we find a
  // non-EH pad. We need to skip over catchswitch blocks, which are both EH pads
  // and terminators.
  auto IDom = DT->getNode(Inst->getParent())->getIDom();
  while (IDom->getBlock()->isEHPad()) {
    assert(Entry != IDom->getBlock() && "eh pad in entry block");
    IDom = IDom->getIDom();
  }

  return IDom->getBlock()->getTerminator();
}

/// Given \p BBs as input, find another set of BBs which collectively
/// dominates \p BBs and have the minimal sum of frequencies. Return the BB
/// set found in \p BBs.
static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI,
                                 BasicBlock *Entry,
                                 SmallPtrSet<BasicBlock *, 8> &BBs) {
  assert(!BBs.count(Entry) && "Assume Entry is not in BBs");
  // Nodes on the current path to the root.
  SmallPtrSet<BasicBlock *, 8> Path;
  // Candidates includes any block 'BB' in set 'BBs' that is not strictly
  // dominated by any other blocks in set 'BBs', and all nodes in the path
  // in the dominator tree from Entry to 'BB'.
  SmallPtrSet<BasicBlock *, 16> Candidates;
  for (auto BB : BBs) {
    Path.clear();
    // Walk up the dominator tree until Entry or another BB in BBs
    // is reached. Insert the nodes on the way to the Path.
    BasicBlock *Node = BB;
    // The "Path" is a candidate path to be added into Candidates set.
    bool isCandidate = false;
    do {
      Path.insert(Node);
      if (Node == Entry || Candidates.count(Node)) {
        isCandidate = true;
        break;
      }
      assert(DT.getNode(Node)->getIDom() &&
             "Entry doens't dominate current Node");
      Node = DT.getNode(Node)->getIDom()->getBlock();
    } while (!BBs.count(Node));

    // If isCandidate is false, Node is another Block in BBs dominating
    // current 'BB'. Drop the nodes on the Path.
    if (!isCandidate)
      continue;

    // Add nodes on the Path into Candidates.
    Candidates.insert(Path.begin(), Path.end());
  }

  // Sort the nodes in Candidates in top-down order and save the nodes
  // in Orders.
  unsigned Idx = 0;
  SmallVector<BasicBlock *, 16> Orders;
  Orders.push_back(Entry);
  while (Idx != Orders.size()) {
    BasicBlock *Node = Orders[Idx++];
    for (auto ChildDomNode : DT.getNode(Node)->getChildren()) {
      if (Candidates.count(ChildDomNode->getBlock()))
        Orders.push_back(ChildDomNode->getBlock());
    }
  }

  // Visit Orders in bottom-up order.
  using InsertPtsCostPair =
      std::pair<SmallPtrSet<BasicBlock *, 16>, BlockFrequency>;

  // InsertPtsMap is a map from a BB to the best insertion points for the
  // subtree of BB (subtree not including the BB itself).
  DenseMap<BasicBlock *, InsertPtsCostPair> InsertPtsMap;
  InsertPtsMap.reserve(Orders.size() + 1);
  for (auto RIt = Orders.rbegin(); RIt != Orders.rend(); RIt++) {
    BasicBlock *Node = *RIt;
    bool NodeInBBs = BBs.count(Node);
    SmallPtrSet<BasicBlock *, 16> &InsertPts = InsertPtsMap[Node].first;
    BlockFrequency &InsertPtsFreq = InsertPtsMap[Node].second;

    // Return the optimal insert points in BBs.
    if (Node == Entry) {
      BBs.clear();
      if (InsertPtsFreq > BFI.getBlockFreq(Node) ||
          (InsertPtsFreq == BFI.getBlockFreq(Node) && InsertPts.size() > 1))
        BBs.insert(Entry);
      else
        BBs.insert(InsertPts.begin(), InsertPts.end());
      break;
    }

    BasicBlock *Parent = DT.getNode(Node)->getIDom()->getBlock();
    // Initially, ParentInsertPts is empty and ParentPtsFreq is 0. Every child
    // will update its parent's ParentInsertPts and ParentPtsFreq.
    SmallPtrSet<BasicBlock *, 16> &ParentInsertPts = InsertPtsMap[Parent].first;
    BlockFrequency &ParentPtsFreq = InsertPtsMap[Parent].second;
    // Choose to insert in Node or in subtree of Node.
    // Don't hoist to EHPad because we may not find a proper place to insert
    // in EHPad.
    // If the total frequency of InsertPts is the same as the frequency of the
    // target Node, and InsertPts contains more than one nodes, choose hoisting
    // to reduce code size.
    if (NodeInBBs ||
        (!Node->isEHPad() &&
         (InsertPtsFreq > BFI.getBlockFreq(Node) ||
          (InsertPtsFreq == BFI.getBlockFreq(Node) && InsertPts.size() > 1)))) {
      ParentInsertPts.insert(Node);
      ParentPtsFreq += BFI.getBlockFreq(Node);
    } else {
      ParentInsertPts.insert(InsertPts.begin(), InsertPts.end());
      ParentPtsFreq += InsertPtsFreq;
    }
  }
}

/// Find an insertion point that dominates all uses.
SmallPtrSet<Instruction *, 8> ConstantHoistingPass::findConstantInsertionPoint(
    const ConstantInfo &ConstInfo) const {
  assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry.");
  // Collect all basic blocks.
  SmallPtrSet<BasicBlock *, 8> BBs;
  SmallPtrSet<Instruction *, 8> InsertPts;
  for (auto const &RCI : ConstInfo.RebasedConstants)
    for (auto const &U : RCI.Uses)
      BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent());

  if (BBs.count(Entry)) {
    InsertPts.insert(&Entry->front());
    return InsertPts;
  }

  if (BFI) {
    findBestInsertionSet(*DT, *BFI, Entry, BBs);
    for (auto BB : BBs) {
      BasicBlock::iterator InsertPt = BB->begin();
      for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
        ;
      InsertPts.insert(&*InsertPt);
    }
    return InsertPts;
  }

  while (BBs.size() >= 2) {
    BasicBlock *BB, *BB1, *BB2;
    BB1 = *BBs.begin();
    BB2 = *std::next(BBs.begin());
    BB = DT->findNearestCommonDominator(BB1, BB2);
    if (BB == Entry) {
      InsertPts.insert(&Entry->front());
      return InsertPts;
    }
    BBs.erase(BB1);
    BBs.erase(BB2);
    BBs.insert(BB);
  }
  assert((BBs.size() == 1) && "Expected only one element.");
  Instruction &FirstInst = (*BBs.begin())->front();
  InsertPts.insert(findMatInsertPt(&FirstInst));
  return InsertPts;
}

/// Record constant integer ConstInt for instruction Inst at operand
/// index Idx.
///
/// The operand at index Idx is not necessarily the constant integer itself. It
/// could also be a cast instruction or a constant expression that uses the
// constant integer.
void ConstantHoistingPass::collectConstantCandidates(
    ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx,
    ConstantInt *ConstInt) {
  unsigned Cost;
  // Ask the target about the cost of materializing the constant for the given
  // instruction and operand index.
  if (auto IntrInst = dyn_cast<IntrinsicInst>(Inst))
    Cost = TTI->getIntImmCost(IntrInst->getIntrinsicID(), Idx,
                              ConstInt->getValue(), ConstInt->getType());
  else
    Cost = TTI->getIntImmCost(Inst->getOpcode(), Idx, ConstInt->getValue(),
                              ConstInt->getType());

  // Ignore cheap integer constants.
  if (Cost > TargetTransformInfo::TCC_Basic) {
    ConstCandMapType::iterator Itr;
    bool Inserted;
    std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(ConstInt, 0));
    if (Inserted) {
      ConstCandVec.push_back(ConstantCandidate(ConstInt));
      Itr->second = ConstCandVec.size() - 1;
    }
    ConstCandVec[Itr->second].addUser(Inst, Idx, Cost);
    LLVM_DEBUG(if (isa<ConstantInt>(Inst->getOperand(Idx))) dbgs()
                   << "Collect constant " << *ConstInt << " from " << *Inst
                   << " with cost " << Cost << '\n';
               else dbgs() << "Collect constant " << *ConstInt
                           << " indirectly from " << *Inst << " via "
                           << *Inst->getOperand(Idx) << " with cost " << Cost
                           << '\n';);
  }
}

/// Check the operand for instruction Inst at index Idx.
void ConstantHoistingPass::collectConstantCandidates(
    ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx) {
  Value *Opnd = Inst->getOperand(Idx);

  // Visit constant integers.
  if (auto ConstInt = dyn_cast<ConstantInt>(Opnd)) {
    collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
    return;
  }

  // Visit cast instructions that have constant integers.
  if (auto CastInst = dyn_cast<Instruction>(Opnd)) {
    // Only visit cast instructions, which have been skipped. All other
    // instructions should have already been visited.
    if (!CastInst->isCast())
      return;

    if (auto *ConstInt = dyn_cast<ConstantInt>(CastInst->getOperand(0))) {
      // Pretend the constant is directly used by the instruction and ignore
      // the cast instruction.
      collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
      return;
    }
  }

  // Visit constant expressions that have constant integers.
  if (auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
    // Only visit constant cast expressions.
    if (!ConstExpr->isCast())
      return;

    if (auto ConstInt = dyn_cast<ConstantInt>(ConstExpr->getOperand(0))) {
      // Pretend the constant is directly used by the instruction and ignore
      // the constant expression.
      collectConstantCandidates(ConstCandMap, Inst, Idx, ConstInt);
      return;
    }
  }
}

/// Scan the instruction for expensive integer constants and record them
/// in the constant candidate vector.
void ConstantHoistingPass::collectConstantCandidates(
    ConstCandMapType &ConstCandMap, Instruction *Inst) {
  // Skip all cast instructions. They are visited indirectly later on.
  if (Inst->isCast())
    return;

  // Scan all operands.
  for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) {
    // The cost of materializing the constants (defined in
    // `TargetTransformInfo::getIntImmCost`) for instructions which only take
    // constant variables is lower than `TargetTransformInfo::TCC_Basic`. So
    // it's safe for us to collect constant candidates from all IntrinsicInsts.
    if (canReplaceOperandWithVariable(Inst, Idx) || isa<IntrinsicInst>(Inst)) {
      collectConstantCandidates(ConstCandMap, Inst, Idx);
    }
  } // end of for all operands
}

/// Collect all integer constants in the function that cannot be folded
/// into an instruction itself.
void ConstantHoistingPass::collectConstantCandidates(Function &Fn) {
  ConstCandMapType ConstCandMap;
  for (BasicBlock &BB : Fn)
    for (Instruction &Inst : BB)
      collectConstantCandidates(ConstCandMap, &Inst);
}

// This helper function is necessary to deal with values that have different
// bit widths (APInt Operator- does not like that). If the value cannot be
// represented in uint64 we return an "empty" APInt. This is then interpreted
// as the value is not in range.
static Optional<APInt> calculateOffsetDiff(const APInt &V1, const APInt &V2) {
  Optional<APInt> Res = None;
  unsigned BW = V1.getBitWidth() > V2.getBitWidth() ?
                V1.getBitWidth() : V2.getBitWidth();
  uint64_t LimVal1 = V1.getLimitedValue();
  uint64_t LimVal2 = V2.getLimitedValue();

  if (LimVal1 == ~0ULL || LimVal2 == ~0ULL)
    return Res;

  uint64_t Diff = LimVal1 - LimVal2;
  return APInt(BW, Diff, true);
}

// From a list of constants, one needs to picked as the base and the other
// constants will be transformed into an offset from that base constant. The
// question is which we can pick best? For example, consider these constants
// and their number of uses:
//
//  Constants| 2 | 4 | 12 | 42 |
//  NumUses  | 3 | 2 |  8 |  7 |
//
// Selecting constant 12 because it has the most uses will generate negative
// offsets for constants 2 and 4 (i.e. -10 and -8 respectively). If negative
// offsets lead to less optimal code generation, then there might be better
// solutions. Suppose immediates in the range of 0..35 are most optimally
// supported by the architecture, then selecting constant 2 is most optimal
// because this will generate offsets: 0, 2, 10, 40. Offsets 0, 2 and 10 are in
// range 0..35, and thus 3 + 2 + 8 = 13 uses are in range. Selecting 12 would
// have only 8 uses in range, so choosing 2 as a base is more optimal. Thus, in
// selecting the base constant the range of the offsets is a very important
// factor too that we take into account here. This algorithm calculates a total
// costs for selecting a constant as the base and substract the costs if
// immediates are out of range. It has quadratic complexity, so we call this
// function only when we're optimising for size and there are less than 100
// constants, we fall back to the straightforward algorithm otherwise
// which does not do all the offset calculations.
unsigned
ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S,
                                           ConstCandVecType::iterator E,
                                           ConstCandVecType::iterator &MaxCostItr) {
  unsigned NumUses = 0;

  if(!Entry->getParent()->optForSize() || std::distance(S,E) > 100) {
    for (auto ConstCand = S; ConstCand != E; ++ConstCand) {
      NumUses += ConstCand->Uses.size();
      if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost)
        MaxCostItr = ConstCand;
    }
    return NumUses;
  }

  LLVM_DEBUG(dbgs() << "== Maximize constants in range ==\n");
  int MaxCost = -1;
  for (auto ConstCand = S; ConstCand != E; ++ConstCand) {
    auto Value = ConstCand->ConstInt->getValue();
    Type *Ty = ConstCand->ConstInt->getType();
    int Cost = 0;
    NumUses += ConstCand->Uses.size();
    LLVM_DEBUG(dbgs() << "= Constant: " << ConstCand->ConstInt->getValue()
                      << "\n");

    for (auto User : ConstCand->Uses) {
      unsigned Opcode = User.Inst->getOpcode();
      unsigned OpndIdx = User.OpndIdx;
      Cost += TTI->getIntImmCost(Opcode, OpndIdx, Value, Ty);
      LLVM_DEBUG(dbgs() << "Cost: " << Cost << "\n");

      for (auto C2 = S; C2 != E; ++C2) {
        Optional<APInt> Diff = calculateOffsetDiff(
                                   C2->ConstInt->getValue(),
                                   ConstCand->ConstInt->getValue());
        if (Diff) {
          const int ImmCosts =
            TTI->getIntImmCodeSizeCost(Opcode, OpndIdx, Diff.getValue(), Ty);
          Cost -= ImmCosts;
          LLVM_DEBUG(dbgs() << "Offset " << Diff.getValue() << " "
                            << "has penalty: " << ImmCosts << "\n"
                            << "Adjusted cost: " << Cost << "\n");
        }
      }
    }
    LLVM_DEBUG(dbgs() << "Cumulative cost: " << Cost << "\n");
    if (Cost > MaxCost) {
      MaxCost = Cost;
      MaxCostItr = ConstCand;
      LLVM_DEBUG(dbgs() << "New candidate: " << MaxCostItr->ConstInt->getValue()
                        << "\n");
    }
  }
  return NumUses;
}

/// Find the base constant within the given range and rebase all other
/// constants with respect to the base constant.
void ConstantHoistingPass::findAndMakeBaseConstant(
    ConstCandVecType::iterator S, ConstCandVecType::iterator E) {
  auto MaxCostItr = S;
  unsigned NumUses = maximizeConstantsInRange(S, E, MaxCostItr);

  // Don't hoist constants that have only one use.
  if (NumUses <= 1)
    return;

  ConstantInfo ConstInfo;
  ConstInfo.BaseConstant = MaxCostItr->ConstInt;
  Type *Ty = ConstInfo.BaseConstant->getType();

  // Rebase the constants with respect to the base constant.
  for (auto ConstCand = S; ConstCand != E; ++ConstCand) {
    APInt Diff = ConstCand->ConstInt->getValue() -
                 ConstInfo.BaseConstant->getValue();
    Constant *Offset = Diff == 0 ? nullptr : ConstantInt::get(Ty, Diff);
    ConstInfo.RebasedConstants.push_back(
      RebasedConstantInfo(std::move(ConstCand->Uses), Offset));
  }
  ConstantVec.push_back(std::move(ConstInfo));
}

/// Finds and combines constant candidates that can be easily
/// rematerialized with an add from a common base constant.
void ConstantHoistingPass::findBaseConstants() {
  // Sort the constants by value and type. This invalidates the mapping!
  llvm::sort(ConstCandVec.begin(), ConstCandVec.end(),
             [](const ConstantCandidate &LHS, const ConstantCandidate &RHS) {
    if (LHS.ConstInt->getType() != RHS.ConstInt->getType())
      return LHS.ConstInt->getType()->getBitWidth() <
             RHS.ConstInt->getType()->getBitWidth();
    return LHS.ConstInt->getValue().ult(RHS.ConstInt->getValue());
  });

  // Simple linear scan through the sorted constant candidate vector for viable
  // merge candidates.
  auto MinValItr = ConstCandVec.begin();
  for (auto CC = std::next(ConstCandVec.begin()), E = ConstCandVec.end();
       CC != E; ++CC) {
    if (MinValItr->ConstInt->getType() == CC->ConstInt->getType()) {
      // Check if the constant is in range of an add with immediate.
      APInt Diff = CC->ConstInt->getValue() - MinValItr->ConstInt->getValue();
      if ((Diff.getBitWidth() <= 64) &&
          TTI->isLegalAddImmediate(Diff.getSExtValue()))
        continue;
    }
    // We either have now a different constant type or the constant is not in
    // range of an add with immediate anymore.
    findAndMakeBaseConstant(MinValItr, CC);
    // Start a new base constant search.
    MinValItr = CC;
  }
  // Finalize the last base constant search.
  findAndMakeBaseConstant(MinValItr, ConstCandVec.end());
}

/// Updates the operand at Idx in instruction Inst with the result of
///        instruction Mat. If the instruction is a PHI node then special
///        handling for duplicate values form the same incoming basic block is
///        required.
/// \return The update will always succeed, but the return value indicated if
///         Mat was used for the update or not.
static bool updateOperand(Instruction *Inst, unsigned Idx, Instruction *Mat) {
  if (auto PHI = dyn_cast<PHINode>(Inst)) {
    // Check if any previous operand of the PHI node has the same incoming basic
    // block. This is a very odd case that happens when the incoming basic block
    // has a switch statement. In this case use the same value as the previous
    // operand(s), otherwise we will fail verification due to different values.
    // The values are actually the same, but the variable names are different
    // and the verifier doesn't like that.
    BasicBlock *IncomingBB = PHI->getIncomingBlock(Idx);
    for (unsigned i = 0; i < Idx; ++i) {
      if (PHI->getIncomingBlock(i) == IncomingBB) {
        Value *IncomingVal = PHI->getIncomingValue(i);
        Inst->setOperand(Idx, IncomingVal);
        return false;
      }
    }
  }

  Inst->setOperand(Idx, Mat);
  return true;
}

/// Emit materialization code for all rebased constants and update their
/// users.
void ConstantHoistingPass::emitBaseConstants(Instruction *Base,
                                             Constant *Offset,
                                             const ConstantUser &ConstUser) {
  Instruction *Mat = Base;
  if (Offset) {
    Instruction *InsertionPt = findMatInsertPt(ConstUser.Inst,
                                               ConstUser.OpndIdx);
    Mat = BinaryOperator::Create(Instruction::Add, Base, Offset,
                                 "const_mat", InsertionPt);

    LLVM_DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0)
                      << " + " << *Offset << ") in BB "
                      << Mat->getParent()->getName() << '\n'
                      << *Mat << '\n');
    Mat->setDebugLoc(ConstUser.Inst->getDebugLoc());
  }
  Value *Opnd = ConstUser.Inst->getOperand(ConstUser.OpndIdx);

  // Visit constant integer.
  if (isa<ConstantInt>(Opnd)) {
    LLVM_DEBUG(dbgs() << "Update: " << *ConstUser.Inst << '\n');
    if (!updateOperand(ConstUser.Inst, ConstUser.OpndIdx, Mat) && Offset)
      Mat->eraseFromParent();
    LLVM_DEBUG(dbgs() << "To    : " << *ConstUser.Inst << '\n');
    return;
  }

  // Visit cast instruction.
  if (auto CastInst = dyn_cast<Instruction>(Opnd)) {
    assert(CastInst->isCast() && "Expected an cast instruction!");
    // Check if we already have visited this cast instruction before to avoid
    // unnecessary cloning.
    Instruction *&ClonedCastInst = ClonedCastMap[CastInst];
    if (!ClonedCastInst) {
      ClonedCastInst = CastInst->clone();
      ClonedCastInst->setOperand(0, Mat);
      ClonedCastInst->insertAfter(CastInst);
      // Use the same debug location as the original cast instruction.
      ClonedCastInst->setDebugLoc(CastInst->getDebugLoc());
      LLVM_DEBUG(dbgs() << "Clone instruction: " << *CastInst << '\n'
                        << "To               : " << *ClonedCastInst << '\n');
    }

    LLVM_DEBUG(dbgs() << "Update: " << *ConstUser.Inst << '\n');
    updateOperand(ConstUser.Inst, ConstUser.OpndIdx, ClonedCastInst);
    LLVM_DEBUG(dbgs() << "To    : " << *ConstUser.Inst << '\n');
    return;
  }

  // Visit constant expression.
  if (auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
    Instruction *ConstExprInst = ConstExpr->getAsInstruction();
    ConstExprInst->setOperand(0, Mat);
    ConstExprInst->insertBefore(findMatInsertPt(ConstUser.Inst,
                                                ConstUser.OpndIdx));

    // Use the same debug location as the instruction we are about to update.
    ConstExprInst->setDebugLoc(ConstUser.Inst->getDebugLoc());

    LLVM_DEBUG(dbgs() << "Create instruction: " << *ConstExprInst << '\n'
                      << "From              : " << *ConstExpr << '\n');
    LLVM_DEBUG(dbgs() << "Update: " << *ConstUser.Inst << '\n');
    if (!updateOperand(ConstUser.Inst, ConstUser.OpndIdx, ConstExprInst)) {
      ConstExprInst->eraseFromParent();
      if (Offset)
        Mat->eraseFromParent();
    }
    LLVM_DEBUG(dbgs() << "To    : " << *ConstUser.Inst << '\n');
    return;
  }
}

/// Hoist and hide the base constant behind a bitcast and emit
/// materialization code for derived constants.
bool ConstantHoistingPass::emitBaseConstants() {
  bool MadeChange = false;
  for (auto const &ConstInfo : ConstantVec) {
    // Hoist and hide the base constant behind a bitcast.
    SmallPtrSet<Instruction *, 8> IPSet = findConstantInsertionPoint(ConstInfo);
    assert(!IPSet.empty() && "IPSet is empty");

    unsigned UsesNum = 0;
    unsigned ReBasesNum = 0;
    for (Instruction *IP : IPSet) {
      IntegerType *Ty = ConstInfo.BaseConstant->getType();
      Instruction *Base =
          new BitCastInst(ConstInfo.BaseConstant, Ty, "const", IP);

      Base->setDebugLoc(IP->getDebugLoc());

      LLVM_DEBUG(dbgs() << "Hoist constant (" << *ConstInfo.BaseConstant
                        << ") to BB " << IP->getParent()->getName() << '\n'
                        << *Base << '\n');

      // Emit materialization code for all rebased constants.
      unsigned Uses = 0;
      for (auto const &RCI : ConstInfo.RebasedConstants) {
        for (auto const &U : RCI.Uses) {
          Uses++;
          BasicBlock *OrigMatInsertBB =
              findMatInsertPt(U.Inst, U.OpndIdx)->getParent();
          // If Base constant is to be inserted in multiple places,
          // generate rebase for U using the Base dominating U.
          if (IPSet.size() == 1 ||
              DT->dominates(Base->getParent(), OrigMatInsertBB)) {
            emitBaseConstants(Base, RCI.Offset, U);
            ReBasesNum++;
          }

          Base->setDebugLoc(DILocation::getMergedLocation(Base->getDebugLoc(), U.Inst->getDebugLoc()));
        }
      }
      UsesNum = Uses;

      // Use the same debug location as the last user of the constant.
      assert(!Base->use_empty() && "The use list is empty!?");
      assert(isa<Instruction>(Base->user_back()) &&
             "All uses should be instructions.");
    }
    (void)UsesNum;
    (void)ReBasesNum;
    // Expect all uses are rebased after rebase is done.
    assert(UsesNum == ReBasesNum && "Not all uses are rebased");

    NumConstantsHoisted++;

    // Base constant is also included in ConstInfo.RebasedConstants, so
    // deduct 1 from ConstInfo.RebasedConstants.size().
    NumConstantsRebased = ConstInfo.RebasedConstants.size() - 1;

    MadeChange = true;
  }
  return MadeChange;
}

/// Check all cast instructions we made a copy of and remove them if they
/// have no more users.
void ConstantHoistingPass::deleteDeadCastInst() const {
  for (auto const &I : ClonedCastMap)
    if (I.first->use_empty())
      I.first->eraseFromParent();
}

/// Optimize expensive integer constants in the given function.
bool ConstantHoistingPass::runImpl(Function &Fn, TargetTransformInfo &TTI,
                                   DominatorTree &DT, BlockFrequencyInfo *BFI,
                                   BasicBlock &Entry) {
  this->TTI = &TTI;
  this->DT = &DT;
  this->BFI = BFI;
  this->Entry = &Entry;
  // Collect all constant candidates.
  collectConstantCandidates(Fn);

  // There are no constant candidates to worry about.
  if (ConstCandVec.empty())
    return false;

  // Combine constants that can be easily materialized with an add from a common
  // base constant.
  findBaseConstants();

  // There are no constants to emit.
  if (ConstantVec.empty())
    return false;

  // Finally hoist the base constant and emit materialization code for dependent
  // constants.
  bool MadeChange = emitBaseConstants();

  // Cleanup dead instructions.
  deleteDeadCastInst();

  return MadeChange;
}

PreservedAnalyses ConstantHoistingPass::run(Function &F,
                                            FunctionAnalysisManager &AM) {
  auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
  auto &TTI = AM.getResult<TargetIRAnalysis>(F);
  auto BFI = ConstHoistWithBlockFrequency
                 ? &AM.getResult<BlockFrequencyAnalysis>(F)
                 : nullptr;
  if (!runImpl(F, TTI, DT, BFI, F.getEntryBlock()))
    return PreservedAnalyses::all();

  PreservedAnalyses PA;
  PA.preserveSet<CFGAnalyses>();
  return PA;
}


text:
div.weatherWidgetContainer {
	background: #5c5c5c ;
	color: white ;
	padding: 3px ;
}

div.weatherWidgetList {
	padding: 10px ;
	border-bottom: 1px solid white ;
}

div.weatherWidgetList h1.weatherWidgetLocation {
	font-size: 2em ;
	color: #d28979 ;
	margin: 0 ;
	padding: 0 ;
}

div.weatherWidgetList p.weatherWidgetSummary {
	color: #ffda6b ;
}

div.weatherWidgetList p.weatherWidgetTemperature {
	color: #ffffff ;
	float: right ;
	font-size: 2em ;
	margin-top: -64px ;
}

div.weatherWidgetList p.weatherWidgetIcon {
	float: right ;
}

div.weatherWidgetCredits {
	font-size: 80% ;
	padding: 0 10px ;
	text-align: right ;
}

div.weatherWidgetContainer a {
	color: #ffda6b ;
}


text:
[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-xinetd.png)](https://travis-ci.org/puppetlabs/puppetlabs-xinetd)

This is the xinetd module.

## Overview

This module configures xinetd, and exposes the xinetd::service definition
for adding new services.

## Class: xinetd

Sets up the xinetd daemon. Has options for you in case you have specific
package names and service needs.

### Parameters

 * `confdir`
 * `conffile`
 * `package_name`
 * `service_name`
 * `service_restart`
 * `service_status`
 * `service_hasrestart`
 * `service_hasstatus`

## Definition: xinetd::service

Sets up a xinetd service. All parameters match up with xinetd.conf(5) man
page.

### Parameters:

 * `server`       - required - determines the program to execute for this service
 * `port`         - required - determines the service port
 * `cps`          - optional
 * `flags`        - optional
 * `per_source`   - optional
 * `server_args`  - optional
 * `disable`      - optional - defaults to "no"
 * `socket_type`  - optional - defaults to "stream"
 * `protocol`     - optional - defaults to "tcp"
 * `user`         - optional - defaults to "root"
 * `group`        - optional - defaults to "root"
 * `instances`    - optional - defaults to "UNLIMITED"
 * `wait`         - optional - based on $protocol will default to "yes" for udp and "no" for tcp
 * `service_type` - optional - type setting in xinetd

### Sample Usage

```puppet
xinetd::service { 'tftp':
  port        => '69',
  server      => '/usr/sbin/in.tftpd',
  server_args => '-s /var/lib/tftp/',
  socket_type => 'dgram',
  protocol    => 'udp',
  cps         => '100 2',
  flags       => 'IPv4',
  per_source  => '11',
}
```

## Supported OSes

Supports Debian, FreeBSD, Suse, RedHat, and Amazon Linux OS Families.


text:
module RecordsHelper

  # convert line endings correctly
  def fix_input_lines(value)
    value.class == String ? value.gsub("\\n", "\n") : value.to_s
  end

  # convert line endings correctly for html
  def fix_html_lines(value)
    value.class == String ? value.gsub("\\n", "
").gsub("\n", "
") : value.to_s
  end

  # add classes to keys and values
  def json_as_html(json)
    # opening table html
    html = "
"
    # for each key
    json.keys.each do |key|
      # add opening row and cell html
      html += "
";
      # add html for the key text
      html += "#{key}";
      # add html for the key input
      html += "<input type='text' class='json-input json-key form-control' value='#{key}'>";
      # add html for the cell
      html += "	";
      # add html for the value text
      html += "#{fix_html_lines(json[key])}";
      # add html for the value textarea
      html += "<textarea class='json-input json-value form-control' rows='8'>#{fix_input_lines(json[key])}</textarea>";
      # add closing cell and row html
      html += "
"
    end
    # closing table html
    html += "
"
    # return the html
    return html
  end

end


text:
package com.ing.baker.runtime.akka

import akka.actor.ActorRef
import akka.persistence.inmemory.extension.{ InMemoryJournalStorage, StorageExtension }
import akka.testkit.TestProbe
import com.ing.baker._
import com.ing.baker.recipe.TestRecipe._
import com.ing.baker.recipe.common.InteractionFailureStrategy
import com.ing.baker.recipe.scaladsl.Recipe
import com.ing.baker.runtime.common.RejectReason._
import com.ing.baker.runtime.scaladsl.{ EventInstance, _ }
import com.ing.baker.types.PrimitiveValue
import com.typesafe.scalalogging.LazyLogging
import java.util.UUID
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.language.postfixOps

object BakerEventsSpec extends LazyLogging {

  def listenerFunction(probe: ActorRef, logEvents: Boolean = false): PartialFunction[BakerEvent, Unit] = {
    case event: BakerEvent =>
      if (logEvents) {
        logger.info("Listener consumed event {}", event)
      }
      probe ! event
  }

  def expectMsgInAnyOrderPF[Out](testProbe: TestProbe, pfs: PartialFunction[Any, Out]*): Unit = {
    if (pfs.nonEmpty) {
      val total = pfs.reduce((a, b) => a.orElse(b))
      testProbe.expectMsgPF() {
        case msg if total.isDefinedAt(msg) =>
          val index = pfs.indexWhere(pf => pf.isDefinedAt(msg))
          pfs(index)(msg)
          expectMsgInAnyOrderPF[Out](testProbe, pfs.take(index) ++ pfs.drop(index + 1): _*)
      }
    }
  }

  // TODO this is a copy of TestRecipe.getRecipe(..) with 1 difference, there is a limit on the initialEvent, why?
  protected def getRecipe(recipeName: String): Recipe =
    Recipe(recipeName)
      .withInteractions(
        interactionOne
          .withEventOutputTransformer(interactionOneSuccessful, Map("interactionOneOriginalIngredient" -> "interactionOneIngredient"))
          .withFailureStrategy(InteractionFailureStrategy.RetryWithIncrementalBackoff(initialDelay = 10 millisecond, maximumRetries = 3)),
        interactionTwo
          .withOverriddenIngredientName("initialIngredientOld", "initialIngredient"),
        interactionThree
          .withMaximumInteractionCount(1),
        interactionFour
          .withRequiredEvents(secondEvent, eventFromInteractionTwo),
        interactionFive,
        interactionSix,
        providesNothingInteraction,
        sieveInteraction
      )
      .withSensoryEvents(
        initialEvent.withMaxFiringLimit(1),
        initialEventExtendedName,
        secondEvent,
        notUsedSensoryEvent)

}

class BakerEventsSpec extends BakerRuntimeTestBase {

  import BakerEventsSpec._

  override def actorSystemName = "BakerEventsSpec"

  private val eventReceiveTimeout = 1 seconds

  before {
    resetMocks()
    setupMockResponse()

    // Clean inmemory-journal before each test
    val tp = TestProbe()
    tp.send(StorageExtension(defaultActorSystem).journalStorage, InMemoryJournalStorage.ClearJournal)
    tp.expectMsg(akka.actor.Status.Success(""))
  }

  "Baker" should {

    "notify ProcessCreated/EventReceived/InteractionStarted/InteractionCompleted events with correct timestamps" in {
      val recipeName = "EventReceivedEventRecipe"
      val recipeInstanceId = UUID.randomUUID().toString
      for {
        (baker, recipeId) <- setupBakerWithRecipe(getRecipe(recipeName), mockImplementations)
        listenerProbe = TestProbe()
        listenerFunction = (bakerEvent: BakerEvent) => listenerProbe.ref ! bakerEvent
        _ <- baker.registerBakerEventListener(listenerFunction)
        _ <- baker.bake(recipeId, recipeInstanceId)
        _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)), "someId")
        // TODO check the order of the timestamps later
        _ = expectMsgInAnyOrderPF(listenerProbe,
        {case msg@RecipeInstanceCreated(_, `recipeId`, `recipeName`, `recipeInstanceId`) => msg},
        {case msg@EventReceived(_, _, _, `recipeInstanceId`, Some("someId"), EventInstance("InitialEvent", ingredients)) if ingredients == Map("initialIngredient" -> PrimitiveValue(`initialIngredientValue`)) => msg},
        {case msg@InteractionStarted(_, _, _, `recipeInstanceId`, "SieveInteraction") => msg},
        {case msg@InteractionStarted(_, _, _, `recipeInstanceId`, "InteractionOne") => msg},
        {case msg@InteractionStarted(_, _, _, `recipeInstanceId`, "InteractionTwo") => msg},
        {case msg@InteractionStarted(_, _, _, `recipeInstanceId`, "InteractionThree") => msg},
        {case msg@InteractionStarted(_, _, _, `recipeInstanceId`, "ProvidesNothingInteraction") => msg},
        {case msg@InteractionCompleted(_, _, _, _, `recipeInstanceId`, "InteractionOne", Some(EventInstance("InteractionOneSuccessful", ingredients))) if ingredients == Map("interactionOneIngredient" -> PrimitiveValue("interactionOneIngredient")) => msg},
        {case msg@InteractionCompleted(_, _, _, _, `recipeInstanceId`, "InteractionTwo", Some(EventInstance("EventFromInteractionTwo", ingredients))) if ingredients == Map("interactionTwoIngredient" -> PrimitiveValue("interactionTwoIngredient")) => msg},
        {case msg@InteractionCompleted(_, _, _, _, `recipeInstanceId`, "InteractionThree", Some(EventInstance("InteractionThreeSuccessful", ingredients))) if ingredients == Map("interactionThreeIngredient" -> PrimitiveValue("interactionThreeIngredient")) => msg},
        {case msg@InteractionCompleted(_, _, _, _, `recipeInstanceId`, "ProvidesNothingInteraction", None) => msg},
        {case msg@InteractionCompleted(_, _, _, _, `recipeInstanceId`, "SieveInteraction", Some(EventInstance("SieveInteractionSuccessful", ingredients))) if ingredients == Map("sievedIngredient" -> PrimitiveValue("sievedIngredient")) => msg}
        )
        _ = listenerProbe.expectNoMessage(eventReceiveTimeout)
      } yield succeed
    }

    "notify EventRejected event with InvalidEvent reason" in {
      val recipeName = "EventRejectedEventRecipe"
      val recipeInstanceId = UUID.randomUUID().toString
      for {
        (baker, recipeId) <- setupBakerWithRecipe(getRecipe(recipeName), mockImplementations)
        listenerProbe = TestProbe()
        listenerFunction = (bakerEvent: BakerEvent) => listenerProbe.ref ! bakerEvent
        _ <- baker.registerBakerEventListener(listenerFunction)
        _ <- baker.bake(recipeId, recipeInstanceId)
        // We used async function here because ThirdEvent is not part of the recipe and throws exception
        _ = baker.fireEventAndResolveWhenReceived(recipeInstanceId, EventInstance.unsafeFrom(ThirdEvent()), "someId")
        _ = listenerProbe.fishForSpecificMessage(eventReceiveTimeout) {
          case msg@EventRejected(_, `recipeInstanceId`, Some("someId"), EventInstance("ThirdEvent", ingredients), InvalidEvent) if ingredients.isEmpty => msg
        }
        _ = listenerProbe.expectNoMessage(eventReceiveTimeout)
      } yield succeed
    }

    "notify EventRejected event with AlreadyReceived reason" in {
      val recipeName = "AlreadyReceivedRecipe"
      val recipeInstanceId = UUID.randomUUID().toString
      for {
        (baker, recipeId) <- setupBakerWithRecipe(getRecipe(recipeName), mockImplementations)
        listenerProbe = TestProbe()
        listenerFunction = (bakerEvent: BakerEvent) => listenerProbe.ref ! bakerEvent
        _ <- baker.registerBakerEventListener(listenerFunction)
        _ <- baker.bake(recipeId, recipeInstanceId)
        _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)), "someId")
        _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)), "someId") // Same correlationId cannot be used twice
        _ = listenerProbe.fishForSpecificMessage(eventReceiveTimeout) {
          case msg@EventRejected(_, `recipeInstanceId`, Some("someId"), EventInstance("InitialEvent", ingredients), AlreadyReceived) if ingredients == Map("initialIngredient" -> PrimitiveValue(`initialIngredientValue`)) => msg
        }
        _ = listenerProbe.expectNoMessage(eventReceiveTimeout)
      } yield succeed
    }

    "notify EventRejected event with FiringLimitMet reason" in {
      val recipeName = "FiringLimitMetRecipe"
      val recipeInstanceId = UUID.randomUUID().toString
      for {
        (baker, recipeId) <- setupBakerWithRecipe(getRecipe(recipeName), mockImplementations)
        listenerProbe = TestProbe()
        listenerFunction = (bakerEvent: BakerEvent) => listenerProbe.ref ! bakerEvent
        _ <- baker.registerBakerEventListener(listenerFunction)
        _ <- baker.bake(recipeId, recipeInstanceId)
        _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)))
        _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))) // Firing limit is set to 1 in the recipe
        _ = listenerProbe.fishForSpecificMessage(eventReceiveTimeout) {
          case msg@EventRejected(_, `recipeInstanceId`, None, EventInstance("InitialEvent", ingredients), FiringLimitMet) if ingredients == Map("initialIngredient" -> PrimitiveValue(`initialIngredientValue`)) => msg
        }
        _ = listenerProbe.expectNoMessage(eventReceiveTimeout)
      } yield succeed
    }

    "notify EventRejected event with ReceivePeriodExpired reason" in {
      val recipeName = "ReceivePeriodExpiredRecipe"
      val recipeInstanceId = UUID.randomUUID().toString
      for {
        (baker, recipeId) <- setupBakerWithRecipe(getRecipe(recipeName).withEventReceivePeriod(eventReceiveTimeout), mockImplementations)
        listenerProbe = TestProbe()
        listenerFunction = (bakerEvent: BakerEvent) => listenerProbe.ref ! bakerEvent
        _ <- baker.registerBakerEventListener(listenerFunction)
        _ <- baker.bake(recipeId, recipeInstanceId)
        _ <- Future {
          Thread.sleep(eventReceiveTimeout.toMillis)
        }
        _ = baker.fireEventAndResolveWhenReceived(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)), "someId")
        _ = listenerProbe.fishForSpecificMessage(eventReceiveTimeout) {
          case msg@EventRejected(_, `recipeInstanceId`, Some("someId"), EventInstance("InitialEvent", ingredients), ReceivePeriodExpired) if ingredients == Map("initialIngredient" -> PrimitiveValue(`initialIngredientValue`)) => msg
        }
        _ = listenerProbe.expectNoMessage(eventReceiveTimeout)
      } yield succeed
    }

    "notify EventRejected event with NoSuchProcess reason" in {
      val recipeName = "NoSuchProcessRecipe"
      val recipeInstanceId = UUID.randomUUID().toString
      for {
        (baker, _) <- setupBakerWithRecipe(getRecipe(recipeName), mockImplementations)
        listenerProbe = TestProbe()
        listenerFunction = (bakerEvent: BakerEvent) => listenerProbe.ref ! bakerEvent
        _ <- baker.registerBakerEventListener(listenerFunction)
        // Skipped baking the process here, so the process with RecipeInstanceId does not exist
        // use a different RecipeInstanceId and use async function because the sync version throws NoSuchProcessException
        _ = baker.fireEventAndResolveWhenReceived(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)), "someId")
        _ = listenerProbe.fishForSpecificMessage(eventReceiveTimeout) {
          case msg@EventRejected(_, `recipeInstanceId`, Some("someId"), EventInstance("InitialEvent", ingredients), NoSuchProcess) if ingredients == Map("initialIngredient" -> PrimitiveValue(`initialIngredientValue`)) => msg
        }
        _ = listenerProbe.expectNoMessage(eventReceiveTimeout)
      } yield succeed
    }
  }
}


text:
Program Reused:: Not
File: /node_modules/a/node_modules/x/index.d.ts

export default class X { private x: number; }
resolvedModules: undefined
resolvedTypeReferenceDirectiveNames: undefined

File: /node_modules/a/index.d.ts

import X from "x";
export function a(x: X): void;
resolvedModules:
x: {"resolvedFileName":"/node_modules/a/node_modules/x/index.d.ts","extension":".d.ts","isExternalLibraryImport":true,"packageId":{"name":"x","subModuleName":"index.d.ts","version":"1.2.3"}}
resolvedTypeReferenceDirectiveNames: undefined

File: /node_modules/b/node_modules/x/index.d.ts

export default class X { private x: number; }
resolvedModules: undefined
resolvedTypeReferenceDirectiveNames: undefined

File: /node_modules/b/index.d.ts

import X from "x";
export const b: X;
resolvedModules:
x: {"resolvedFileName":"/node_modules/b/node_modules/x/index.d.ts","extension":".d.ts","isExternalLibraryImport":true,"packageId":{"name":"x","subModuleName":"index.d.ts","version":"1.2.3"}}
resolvedTypeReferenceDirectiveNames: undefined

File: /a.ts

import { a } from "a"; import { b } from "b";
a(b)
resolvedModules:
a: {"resolvedFileName":"/node_modules/a/index.d.ts","extension":".d.ts","isExternalLibraryImport":true}
b: {"resolvedFileName":"/node_modules/b/index.d.ts","extension":".d.ts","isExternalLibraryImport":true}
resolvedTypeReferenceDirectiveNames: undefined

MissingPaths:: ["lib.d.ts"]

Program Reused:: Not
File: /node_modules/a/node_modules/x/index.d.ts

export default class X { private x: number; private y: number; }
resolvedModules: undefined
resolvedTypeReferenceDirectiveNames: undefined

File: /node_modules/a/index.d.ts

import X from "x";
export function a(x: X): void;
resolvedModules:
x: {"resolvedFileName":"/node_modules/a/node_modules/x/index.d.ts","extension":".d.ts","isExternalLibraryImport":true}
resolvedTypeReferenceDirectiveNames: undefined

File: /node_modules/b/node_modules/x/index.d.ts

export default class X { private x: number; }
resolvedModules: undefined
resolvedTypeReferenceDirectiveNames: undefined

File: /node_modules/b/index.d.ts

import X from "x";
export const b: X;
resolvedModules:
x: {"resolvedFileName":"/node_modules/b/node_modules/x/index.d.ts","extension":".d.ts","isExternalLibraryImport":true,"packageId":{"name":"x","subModuleName":"index.d.ts","version":"1.2.3"}}
resolvedTypeReferenceDirectiveNames: undefined

File: /a.ts

import { a } from "a"; import { b } from "b";
a(b)
resolvedModules:
a: {"resolvedFileName":"/node_modules/a/index.d.ts","extension":".d.ts","isExternalLibraryImport":true}
b: {"resolvedFileName":"/node_modules/b/index.d.ts","extension":".d.ts","isExternalLibraryImport":true}
resolvedTypeReferenceDirectiveNames: undefined

MissingPaths:: ["lib.d.ts"]

/a.ts(3,3): error TS2345: Argument of type 'import("/node_modules/b/node_modules/x/index").default' is not assignable to parameter of type 'import("/node_modules/a/node_modules/x/index").default'.
  Property 'y' is missing in type 'import("/node_modules/b/node_modules/x/index").default' but required in type 'import("/node_modules/a/node_modules/x/index").default'.


text:
package de.daxu.swamp.core.datacenter;

import de.daxu.swamp.core.server.Server;
import de.daxu.swamp.test.rule.IntegrationTestRule;
import de.daxu.swamp.test.rule.SpringRule;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;

import static de.daxu.swamp.common.comparator.ReflectionComparator.byReflection;
import static de.daxu.swamp.core.LocationTestConstants.Datacenters.*;
import static de.daxu.swamp.core.LocationTestConstants.Servers.aServer;
import static de.daxu.swamp.test.rule.SpringRule.spring;
import static org.assertj.core.api.Assertions.assertThat;

public class DatacenterServiceIntegrationTest {

    @ClassRule
    public static SpringRule spring = spring();
    @Rule
    public IntegrationTestRule integration = new IntegrationTestRule(spring);

    private DatacenterService datacenterService
            = spring.getInstance(DatacenterService.class);

    @Test
    public void addServerToDatacenter() throws Exception {
        Datacenter datacenter = aDatacenter();
        Server server = aServer();
        integration.save(datacenter);

        datacenterService.addServerToDatacenter(datacenter.getId(), server);

        Datacenter actual = integration.find(datacenter.getId(), Datacenter.class);
        assertThat(actual.getServers())
                .usingElementComparator(byReflection())
                .contains(server);
    }

    @Test
    public void removeServerFromDatacenter() throws Exception {
        Server server = aServer();
        Datacenter datacenter = aDatacenter(server);
        integration.save(datacenter);

        datacenterService.removeServerFromDatacenter(datacenter.getId(), server);

        Datacenter actual = integration.find(datacenter.getId(), Datacenter.class);
        assertThat(actual.getServers()).isEmpty();
    }

    @Test
    public void updateDatacenter() throws Exception {
        Datacenter datacenter = aDatacenter();
        integration.save(datacenter);

        datacenter.setName(ANOTHER_DATACENTER_NAME);
        Datacenter actual = datacenterService.updateDatacenter(datacenter);

        assertThat(actual)
                .usingComparator(byReflection())
                .isEqualTo(aDatacenterBuilder()
                        .withName(ANOTHER_DATACENTER_NAME)
                        .build());
    }

    @Test
    public void getDatacenter() throws Exception {
        Datacenter datacenter = aDatacenter();
        integration.save(datacenter);

        Datacenter actual = datacenterService.getDatacenter(datacenter.getId());

        assertThat(actual)
                .usingComparator(byReflection())
                .isEqualTo(datacenter);
    }

}


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;

using Internal.Runtime;
using Internal.Text;
using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis
{
    public class InterfaceDispatchCellNode : ObjectNode, ISymbolNode
    {
        MethodDesc _targetMethod;
        string _callSiteIdentifier;

        public InterfaceDispatchCellNode(MethodDesc targetMethod, string callSiteIdentifier)
        {
            Debug.Assert(targetMethod.OwningType.IsInterface);
            Debug.Assert(!targetMethod.IsSharedByGenericInstantiations);
            _targetMethod = targetMethod;
            _callSiteIdentifier = callSiteIdentifier;
        }

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(GetMangledName(nameMangler, _targetMethod, _callSiteIdentifier));
        }
        public int Offset => 0;

        public override bool IsShareable => false;

        public static string GetMangledName(NameMangler nameMangler, MethodDesc method, string callSiteIdentifier)
        {
            string name = nameMangler.CompilationUnitPrefix + "__InterfaceDispatchCell_" + nameMangler.GetMangledMethodName(method);

            if (!string.IsNullOrEmpty(callSiteIdentifier))
            {
                name += "_" + callSiteIdentifier;
            }

            return name;
        }

        protected override string GetName() => this.GetMangledName();

        public override ObjectNodeSection Section => ObjectNodeSection.DataSection;

        public override bool StaticDependenciesAreComputed => true;

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder objData = new ObjectDataBuilder(factory);
            // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the
            // synchronization mechanism of the two values in the runtime.
            objData.RequireInitialAlignment(_targetMethod.Context.Target.PointerSize * 2);
            objData.AddSymbol(this);

            if (factory.Target.Architecture == TargetArchitecture.ARM)
            {
                objData.EmitPointerReloc(factory.InitialInterfaceDispatchStub);
            }
            else
            {
                objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch"));
            }

            if (factory.Target.Abi == TargetAbi.CoreRT)
            {
                // TODO: Enable Indirect Pointer for Interface Dispatch Cell. See https://github.com/dotnet/corert/issues/2542
                objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType),
                    (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsInterfacePointerOrMetadataToken);
            }
            else
            {
                if (factory.CompilationModuleGroup.ContainsType(_targetMethod.OwningType))
                {
                    objData.EmitReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), RelocType.IMAGE_REL_BASED_RELPTR32,
                        (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsInterfaceRelativePointer);
                }
                else
                {
                    objData.EmitReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), RelocType.IMAGE_REL_BASED_RELPTR32,
                        (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsIndirectedInterfaceRelativePointer);
                }

                if (objData.TargetPointerSize == 8)
                {
                    // IMAGE_REL_BASED_RELPTR is a 32-bit relocation. However, the cell needs a full pointer
                    // width there since a pointer to the cache will be written into the cell. Emit additional
                    // 32 bits on targets whose pointer size is 64 bit.
                    objData.EmitInt(0);
                }
            }

            // End the run of dispatch cells
            objData.EmitZeroPointer();

            // Avoid consulting VTable slots until they're guaranteed complete during final data emission
            if (!relocsOnly)
            {
                objData.EmitNaturalInt(VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod));
            }

            return objData.ToObjectData();
        }
    }
}