/* iCheck plugin Square skin
----------------------------------- */
.icheckbox_square,
.iradio_square {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(square.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square {
    background-position: 0 0;
}
    .icheckbox_square.hover {
        background-position: -24px 0;
    }
    .icheckbox_square.checked {
        background-position: -48px 0;
    }
    .icheckbox_square.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square {
    background-position: -120px 0;
}
    .iradio_square.hover {
        background-position: -144px 0;
    }
    .iradio_square.checked {
        background-position: -168px 0;
    }
    .iradio_square.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square,
    .iradio_square {
        background-image: url(square@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* red */
.icheckbox_square-red,
.iradio_square-red {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(red.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-red {
    background-position: 0 0;
}
    .icheckbox_square-red.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-red.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-red.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-red.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-red {
    background-position: -120px 0;
}
    .iradio_square-red.hover {
        background-position: -144px 0;
    }
    .iradio_square-red.checked {
        background-position: -168px 0;
    }
    .iradio_square-red.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-red.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-red,
    .iradio_square-red {
        background-image: url(red@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* green */
.icheckbox_square-green,
.iradio_square-green {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(green.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-green {
    background-position: 0 0;
}
    .icheckbox_square-green.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-green.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-green.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-green.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-green {
    background-position: -120px 0;
}
    .iradio_square-green.hover {
        background-position: -144px 0;
    }
    .iradio_square-green.checked {
        background-position: -168px 0;
    }
    .iradio_square-green.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-green.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-green,
    .iradio_square-green {
        background-image: url(green@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* blue */
.icheckbox_square-blue,
.iradio_square-blue {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(blue.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-blue {
    background-position: 0 0;
}
    .icheckbox_square-blue.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-blue.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-blue.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-blue.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-blue {
    background-position: -120px 0;
}
    .iradio_square-blue.hover {
        background-position: -144px 0;
    }
    .iradio_square-blue.checked {
        background-position: -168px 0;
    }
    .iradio_square-blue.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-blue.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-blue,
    .iradio_square-blue {
        background-image: url(blue@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* aero */
.icheckbox_square-aero,
.iradio_square-aero {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(aero.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-aero {
    background-position: 0 0;
}
    .icheckbox_square-aero.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-aero.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-aero.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-aero.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-aero {
    background-position: -120px 0;
}
    .iradio_square-aero.hover {
        background-position: -144px 0;
    }
    .iradio_square-aero.checked {
        background-position: -168px 0;
    }
    .iradio_square-aero.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-aero.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-aero,
    .iradio_square-aero {
        background-image: url(aero@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* grey */
.icheckbox_square-grey,
.iradio_square-grey {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(grey.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-grey {
    background-position: 0 0;
}
    .icheckbox_square-grey.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-grey.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-grey.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-grey.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-grey {
    background-position: -120px 0;
}
    .iradio_square-grey.hover {
        background-position: -144px 0;
    }
    .iradio_square-grey.checked {
        background-position: -168px 0;
    }
    .iradio_square-grey.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-grey.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-grey,
    .iradio_square-grey {
        background-image: url(grey@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* orange */
.icheckbox_square-orange,
.iradio_square-orange {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(orange.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-orange {
    background-position: 0 0;
}
    .icheckbox_square-orange.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-orange.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-orange.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-orange.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-orange {
    background-position: -120px 0;
}
    .iradio_square-orange.hover {
        background-position: -144px 0;
    }
    .iradio_square-orange.checked {
        background-position: -168px 0;
    }
    .iradio_square-orange.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-orange.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-orange,
    .iradio_square-orange {
        background-image: url(orange@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* yellow */
.icheckbox_square-yellow,
.iradio_square-yellow {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(yellow.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-yellow {
    background-position: 0 0;
}
    .icheckbox_square-yellow.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-yellow.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-yellow.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-yellow.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-yellow {
    background-position: -120px 0;
}
    .iradio_square-yellow.hover {
        background-position: -144px 0;
    }
    .iradio_square-yellow.checked {
        background-position: -168px 0;
    }
    .iradio_square-yellow.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-yellow.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-yellow,
    .iradio_square-yellow {
        background-image: url(yellow@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* pink */
.icheckbox_square-pink,
.iradio_square-pink {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(pink.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-pink {
    background-position: 0 0;
}
    .icheckbox_square-pink.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-pink.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-pink.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-pink.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-pink {
    background-position: -120px 0;
}
    .iradio_square-pink.hover {
        background-position: -144px 0;
    }
    .iradio_square-pink.checked {
        background-position: -168px 0;
    }
    .iradio_square-pink.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-pink.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-pink,
    .iradio_square-pink {
        background-image: url(pink@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}

/* purple */
.icheckbox_square-purple,
.iradio_square-purple {
    display: inline-block;
    *display: inline;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    width: 22px;
    height: 22px;
    background: url(purple.png) no-repeat;
    border: none;
    cursor: pointer;
}

.icheckbox_square-purple {
    background-position: 0 0;
}
    .icheckbox_square-purple.hover {
        background-position: -24px 0;
    }
    .icheckbox_square-purple.checked {
        background-position: -48px 0;
    }
    .icheckbox_square-purple.disabled {
        background-position: -72px 0;
        cursor: default;
    }
    .icheckbox_square-purple.checked.disabled {
        background-position: -96px 0;
    }

.iradio_square-purple {
    background-position: -120px 0;
}
    .iradio_square-purple.hover {
        background-position: -144px 0;
    }
    .iradio_square-purple.checked {
        background-position: -168px 0;
    }
    .iradio_square-purple.disabled {
        background-position: -192px 0;
        cursor: default;
    }
    .iradio_square-purple.checked.disabled {
        background-position: -216px 0;
    }

/* Retina support */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (-moz-min-device-pixel-ratio: 1.5),
       only screen and (-o-min-device-pixel-ratio: 3/2),
       only screen and (min-device-pixel-ratio: 1.5) {
    .icheckbox_square-purple,
    .iradio_square-purple {
        background-image: url(purple@2x.png);
        -webkit-background-size: 240px 24px;
        background-size: 240px 24px;
    }
}


import fnmatch
import collections

ALIAS_SECTION = "aliases"

class HostlistError(Exception):
    pass

class UnresolvableAliasError(HostlistError):

    def __init__(self, glob):
        self.glob = glob
        super(UnresolvableAliasError, self).__init__()

    def __str__(self):
        return "unresolvable alias: %r matched no hosts" % self.glob

class UnresolvableHostRefError(HostlistError):

    def __init__(self, host_ref):
        self.host_ref = host_ref
        super(UnresolvableHostRefError, self).__init__()

    def __str__(self):
        return "no host or alias found for %r" % self.host_ref

class HostSelectionError(HostlistError):
    pass

def parse_aliases(config_parser):
    if not config_parser.has_section(ALIAS_SECTION):
        return {}

    aliases = {}
    for key, value in config_parser.items(ALIAS_SECTION):
        aliases[key] = value.split()
    return aliases

def resolve_alias(all_hosts, globs):
    hosts = []

    for glob in globs:
        globbed = [host for host in all_hosts
                   if fnmatch.fnmatch(host.name, glob)]
        if not globbed:
            raise UnresolvableAliasError(glob)
        hosts.extend(globbed)
    return hosts

def resolve_hostlist(host_refs, all_hosts, aliases):
    resolved_hosts = []

    for ref in host_refs:
        if ref in aliases:
            hosts = resolve_alias(all_hosts, aliases[ref])
            resolved_hosts.extend(hosts)
        else:
            matching_hosts = [host for host in all_hosts if host.name == ref]

            if matching_hosts:
                resolved_hosts.extend(matching_hosts)
            else:
                raise UnresolvableHostRefError(ref)

    return resolved_hosts

def select_canaries(hosts):
    """Pick representative canary hosts from the full host list.

    The goals are:

    * the canaries should represent all pools in the hostlist
    * the first host should be from the most common pool
        * if it's a bad deploy it affects the pool with the most capacity.
        * hopefully the largest pool will have the most traffic to test on.
    * the ordering should be stable for repeatability on revert

    To achieve this, we take one host from each pool ordering the pools by
    descending size and the hosts within a pool by instance ID.

    """
    by_pool = collections.defaultdict(list)
    for host in hosts:
        by_pool[host.pool].append(host)

    by_pool_ordered_by_pool_size = sorted(
        by_pool.iteritems(),
        key=lambda (pool_name, hosts): len(hosts),
        reverse=True,
    )

    canaries = []
    for pool, hosts in by_pool_ordered_by_pool_size:
        canary_for_pool = sorted(hosts, key=lambda h: h.id)[0]
        canaries.append(canary_for_pool)
    return canaries


/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include <climits>
#include <vector>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/video_source.h"
#include "test/util.h"

// Enable(1) or Disable(0) writing of the compressed bitstream.
#define WRITE_COMPRESSED_STREAM 0

namespace {

#if WRITE_COMPRESSED_STREAM
static void mem_put_le16(char *const mem, const unsigned int val) {
  mem[0] = val;
  mem[1] = val >> 8;
}

static void mem_put_le32(char *const mem, const unsigned int val) {
  mem[0] = val;
  mem[1] = val >> 8;
  mem[2] = val >> 16;
  mem[3] = val >> 24;
}

static void write_ivf_file_header(const vpx_codec_enc_cfg_t *const cfg,
                                  int frame_cnt, FILE *const outfile) {
  char header[32];

  header[0] = 'D';
  header[1] = 'K';
  header[2] = 'I';
  header[3] = 'F';
  mem_put_le16(header + 4,  0);                   /* version */
  mem_put_le16(header + 6,  32);                  /* headersize */
  mem_put_le32(header + 8,  0x30395056);          /* fourcc (vp9) */
  mem_put_le16(header + 12, cfg->g_w);            /* width */
  mem_put_le16(header + 14, cfg->g_h);            /* height */
  mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
  mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
  mem_put_le32(header + 24, frame_cnt);           /* length */
  mem_put_le32(header + 28, 0);                   /* unused */

  (void)fwrite(header, 1, 32, outfile);
}

static void write_ivf_frame_size(FILE *const outfile, const size_t size) {
  char header[4];
  mem_put_le32(header, static_cast<unsigned int>(size));
  (void)fwrite(header, 1, 4, outfile);
}

static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt,
                                   FILE *const outfile) {
  char header[12];
  vpx_codec_pts_t pts;

  if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
    return;

  pts = pkt->data.frame.pts;
  mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz));
  mem_put_le32(header + 4, pts & 0xFFFFFFFF);
  mem_put_le32(header + 8, pts >> 32);

  (void)fwrite(header, 1, 12, outfile);
}
#endif  // WRITE_COMPRESSED_STREAM

const unsigned int kInitialWidth = 320;
const unsigned int kInitialHeight = 240;

unsigned int ScaleForFrameNumber(unsigned int frame, unsigned int val) {
  if (frame < 10)
    return val;
  if (frame < 20)
    return val / 2;
  if (frame < 30)
    return val * 2 / 3;
  if (frame < 40)
    return val / 4;
  if (frame < 50)
    return val * 7 / 8;
  return val;
}

class ResizingVideoSource : public ::libvpx_test::DummyVideoSource {
 public:
  ResizingVideoSource() {
    SetSize(kInitialWidth, kInitialHeight);
    limit_ = 60;
  }

  virtual ~ResizingVideoSource() {}

 protected:
  virtual void Next() {
    ++frame_;
    SetSize(ScaleForFrameNumber(frame_, kInitialWidth),
            ScaleForFrameNumber(frame_, kInitialHeight));
    FillFrame();
  }
};

class ResizeTest : public ::libvpx_test::EncoderTest,
  public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
 protected:
  ResizeTest() : EncoderTest(GET_PARAM(0)) {}

  virtual ~ResizeTest() {}

  struct FrameInfo {
    FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
        : pts(_pts), w(_w), h(_h) {}

    vpx_codec_pts_t pts;
    unsigned int w;
    unsigned int h;
  };

  virtual void SetUp() {
    InitializeConfig();
    SetMode(GET_PARAM(1));
  }

  virtual void DecompressedFrameHook(const vpx_image_t &img,
                                     vpx_codec_pts_t pts) {
    frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
  }

  std::vector< FrameInfo > frame_info_list_;
};

TEST_P(ResizeTest, TestExternalResizeWorks) {
  ResizingVideoSource video;
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));

  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
       info != frame_info_list_.end(); ++info) {
    const unsigned int frame = static_cast<unsigned>(info->pts);
    const unsigned int expected_w = ScaleForFrameNumber(frame, kInitialWidth);
    const unsigned int expected_h = ScaleForFrameNumber(frame, kInitialHeight);

    EXPECT_EQ(expected_w, info->w)
        << "Frame " << frame << "had unexpected width";
    EXPECT_EQ(expected_h, info->h)
        << "Frame " << frame << "had unexpected height";
  }
}

const unsigned int kStepDownFrame = 3;
const unsigned int kStepUpFrame = 6;

class ResizeInternalTest : public ResizeTest {
 protected:
#if WRITE_COMPRESSED_STREAM
  ResizeInternalTest()
      : ResizeTest(),
        frame0_psnr_(0.0),
        outfile_(NULL),
        out_frames_(0) {}
#else
  ResizeInternalTest() : ResizeTest(), frame0_psnr_(0.0) {}
#endif

  virtual ~ResizeInternalTest() {}

  virtual void BeginPassHook(unsigned int /*pass*/) {
#if WRITE_COMPRESSED_STREAM
    outfile_ = fopen("vp90-2-05-resize.ivf", "wb");
#endif
  }

  virtual void EndPassHook() {
#if WRITE_COMPRESSED_STREAM
    if (outfile_) {
      if (!fseek(outfile_, 0, SEEK_SET))
        write_ivf_file_header(&cfg_, out_frames_, outfile_);
      fclose(outfile_);
      outfile_ = NULL;
    }
#endif
  }

  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
                                  libvpx_test::Encoder *encoder) {
    if (video->frame() == kStepDownFrame) {
      struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE};
      encoder->Control(VP8E_SET_SCALEMODE, &mode);
    }
    if (video->frame() == kStepUpFrame) {
      struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
      encoder->Control(VP8E_SET_SCALEMODE, &mode);
    }
  }

  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
    if (!frame0_psnr_)
      frame0_psnr_ = pkt->data.psnr.psnr[0];
    EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
  }

  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
#if WRITE_COMPRESSED_STREAM
    ++out_frames_;

    // Write initial file header if first frame.
    if (pkt->data.frame.pts == 0)
      write_ivf_file_header(&cfg_, 0, outfile_);

    // Write frame header and data.
    write_ivf_frame_header(pkt, outfile_);
    (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
#endif
  }

  double frame0_psnr_;
#if WRITE_COMPRESSED_STREAM
  FILE *outfile_;
  unsigned int out_frames_;
#endif
};

TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       30, 1, 0, 10);
  init_flags_ = VPX_CODEC_USE_PSNR;

  // q picked such that initial keyframe on this clip is ~30dB PSNR
  cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;

  // If the number of frames being encoded is smaller than g_lag_in_frames
  // the encoded frame is unavailable using the current API. Comparing
  // frames to detect mismatch would then not be possible. Set
  // g_lag_in_frames = 0 to get around this.
  cfg_.g_lag_in_frames = 0;
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));

  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
       info != frame_info_list_.end(); ++info) {
    const vpx_codec_pts_t pts = info->pts;
    if (pts >= kStepDownFrame && pts < kStepUpFrame) {
      ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
      ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
    } else {
      EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
      EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
    }
  }
}

VP8_INSTANTIATE_TEST_CASE(ResizeTest, ONE_PASS_TEST_MODES);
VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest,
                          ::testing::Values(::libvpx_test::kOnePassBest));
}  // namespace


package MusicBrainz::Server::Data::Recording;

use Moose;
use namespace::autoclean;
use List::UtilsBy qw( rev_nsort_by sort_by uniq_by );
use MusicBrainz::Server::Constants qw(
    $EDIT_RECORDING_CREATE
    $EDIT_HISTORIC_ADD_TRACK
    $EDIT_HISTORIC_ADD_TRACK_KV
);
use MusicBrainz::Server::Data::Track;
use MusicBrainz::Server::Data::ReleaseGroup;
use MusicBrainz::Server::Data::Utils qw(
    defined_hash
    hash_to_row
    merge_boolean_attributes
    merge_table_attributes
    placeholders
    load_subobjects
    order_by
);
use MusicBrainz::Server::Entity::Recording;

extends 'MusicBrainz::Server::Data::CoreEntity';
with 'MusicBrainz::Server::Data::Role::Annotation' => { type => 'recording' };
with 'MusicBrainz::Server::Data::Role::CoreEntityCache';
with 'MusicBrainz::Server::Data::Role::DeleteAndLog' => { type => 'recording' };
with 'MusicBrainz::Server::Data::Role::Editable' => { table => 'recording' };
with 'MusicBrainz::Server::Data::Role::Rating' => { type => 'recording' };
with 'MusicBrainz::Server::Data::Role::Tag' => { type => 'recording' };
with 'MusicBrainz::Server::Data::Role::LinksToEdit' => { table => 'recording' };
with 'MusicBrainz::Server::Data::Role::Merge';
with 'MusicBrainz::Server::Data::Role::Alias' => { type => 'recording' };
with 'MusicBrainz::Server::Data::Role::Collection';

sub _type { 'recording' }

sub _columns
{
    return 'recording.id, recording.gid, recording.name,
            recording.artist_credit AS artist_credit_id,
            recording.length, recording.comment, recording.video,
            recording.edits_pending, recording.last_updated';
}
sub _column_mapping
{
    return {
        id               => 'id',
        gid              => 'gid',
        name             => 'name',
        artist_credit_id => 'artist_credit_id',
        length           => 'length',
        comment          => 'comment',
        video            => 'video',
        edits_pending    => 'edits_pending',
        last_updated     => 'last_updated',
    };
}

sub _id_column
{
    return 'recording.id';
}

sub find_artist_credits_by_artist
{
    my ($self, $artist_id) = @_;

    my $query = "SELECT DISTINCT rec.artist_credit
                 FROM recording rec
                 JOIN artist_credit_name acn
                     ON acn.artist_credit = rec.artist_credit
                 WHERE acn.artist = ?";
    my $ids = $self->sql->select_single_column_array($query, $artist_id);
    return $self->c->model('ArtistCredit')->find_by_ids($ids);
}

sub find_by_artist
{
    my ($self, $artist_id, $limit, $offset, %args) = @_;

    my (@where_query, @where_args);

    push @where_query, "acn.artist = ?";
    push @where_args, $artist_id;

    if (exists $args{filter}) {
        my %filter = %{ $args{filter} };
        if (exists $filter{name}) {
            push @where_query, "(mb_simple_tsvector(recording.name) @@ plainto_tsquery('mb_simple', mb_lower(?)) OR recording.name = ?)";
            push @where_args, $filter{name}, $filter{name};
        }
        if (exists $filter{artist_credit_id}) {
            push @where_query, "recording.artist_credit = ?";
            push @where_args, $filter{artist_credit_id};
        }
    }

    my $query = "SELECT DISTINCT " . $self->_columns . ",
                        recording.name COLLATE musicbrainz AS name_collate,
                        comment COLLATE musicbrainz AS comment_collate
                 FROM " . $self->_table . "
                     JOIN artist_credit_name acn
                         ON acn.artist_credit = recording.artist_credit
                 WHERE " . join(" AND ", @where_query) . "
                 ORDER BY recording.name COLLATE musicbrainz,
                          comment COLLATE musicbrainz";
    $self->query_to_list_limited($query, \@where_args, $limit, $offset);
}

sub find_by_instrument {
    my ($self, $instrument_id, $limit, $offset) = @_;

    # NOTE: if more tables than l_artist_recording are added here, check admin/BuildSitemaps.pl
    my $query = "SELECT " . $self->_columns . ",
                     array_agg(json_build_object('typeName', link_type.name, 'credit', lac.credited_as)) AS instrument_credits_and_rel_types
                 FROM " . $self->_table . "
                     JOIN l_artist_recording ON l_artist_recording.entity1 = recording.id
                     JOIN link ON link.id = l_artist_recording.link
                     JOIN link_type ON link_type.id = link.link_type
                     JOIN link_attribute ON link_attribute.link = link.id
                     JOIN link_attribute_type ON link_attribute_type.id = link_attribute.attribute_type
                     JOIN instrument ON instrument.gid = link_attribute_type.gid
                     LEFT JOIN link_attribute_credit lac ON (
                         lac.link = link_attribute.link AND
                         lac.attribute_type = link_attribute.attribute_type
                     )
                 WHERE instrument.id = ?
                 GROUP BY recording.id
                 ORDER BY recording.name COLLATE musicbrainz";

    $self->query_to_list_limited(
        $query,
        [$instrument_id],
        $limit,
        $offset,
        sub {
            my ($model, $row) = @_;
            my $credits_and_rel_types = delete $row->{instrument_credits_and_rel_types};
            { recording => $model->_new_from_row($row), instrument_credits_and_rel_types => $credits_and_rel_types };
        },
    );
}

sub find_by_release
{
    my ($self, $release_id, $limit, $offset) = @_;

    my $query = "SELECT " . $self->_columns . "
                 FROM " . $self->_table . "
                     JOIN track ON track.recording = recording.id
                     JOIN medium ON medium.id = track.medium
                     JOIN release ON release.id = medium.release
                 WHERE release.id = ?
                 ORDER BY recording.name COLLATE musicbrainz";

    $self->query_to_list_limited($query, [$release_id], $limit, $offset);
}

sub find_by_works
{
    my ($self, $work_ids, $limit, $offset) = @_;
    return ([], 0) unless @$work_ids;

    my $query = "SELECT " . $self->_columns . "
                 FROM ". $self->_table . "
                     JOIN l_recording_work lrw ON lrw.entity0 = recording.id
                 WHERE lrw.entity1 = any(?)
                 ORDER BY recording.name COLLATE musicbrainz";

    $self->query_to_list_limited($query, [$work_ids], $limit, $offset);
}

sub _order_by {
    my ($self, $order) = @_;

    my $extra_join = "";
    my $also_select = "";

    my $order_by = order_by($order, "name", {
        "name" => sub {
            return "name COLLATE musicbrainz"
        },
        "artist" => sub {
            $extra_join = "JOIN artist_credit ac ON ac.id = recording.artist_credit";
            $also_select = "ac.name AS ac_name";
            return "ac_name COLLATE musicbrainz, recording.name COLLATE musicbrainz";
        },
        "length" => sub {
            return "length, name COLLATE musicbrainz"
        },
    });

    my $inner_order_by = $order_by
        =~ s/ac_name/ac.name/r;

    return ($order_by, $extra_join, $also_select, $inner_order_by);
}

sub can_delete {
    my ($self, $recording_id) = @_;
    return !$self->sql->select_single_value(
        'SELECT 1 FROM track WHERE recording = ? LIMIT 1',
        $recording_id
    );
}

sub load
{
    my ($self, @objs) = @_;
    return load_subobjects($self, 'recording', @objs);
}

sub update
{
    my ($self, $recording_id, $update) = @_;
    my $row = $self->_hash_to_row($update);
    $self->sql->update_row('recording', $row, { id => $recording_id });
}

sub usage_count
{
    my ($self, $recording_id) = @_;
    return $self->sql->select_single_value(
        'SELECT count(*) FROM track
          WHERE recording = ?', $recording_id);
}

sub delete
{
    my ($self, @recording_ids) = @_;

    $self->c->model('Collection')->delete_entities('recording', @recording_ids);
    $self->c->model('Relationship')->delete_entities('recording', @recording_ids);
    $self->c->model('ISRC')->delete_recordings(@recording_ids);
    $self->alias->delete_entities(@recording_ids);
    $self->annotation->delete(@recording_ids);
    $self->tags->delete(@recording_ids);
    $self->rating->delete(@recording_ids);
    $self->remove_gid_redirects(@recording_ids);
    $self->delete_returning_gids(@recording_ids);
    return;
}

sub _hash_to_row
{
    my ($self, $recording) = @_;
    my $row = hash_to_row($recording, {
        video => 'video',
        map { $_ => $_ } qw( artist_credit length comment name )
    });

    return $row;
}

sub load_meta
{
    my $self = shift;
    MusicBrainz::Server::Data::Utils::load_meta($self->c, "recording_meta", sub {
        my ($obj, $row) = @_;
        $obj->rating($row->{rating}) if defined $row->{rating};
        $obj->rating_count($row->{rating_count}) if defined $row->{rating_count};
    }, @_);
}

sub _merge_impl
{
    my ($self, $new_id, @old_ids) = @_;

    $self->alias->merge($new_id, @old_ids);
    $self->annotation->merge($new_id, @old_ids);
    $self->tags->merge($new_id, @old_ids);
    $self->rating->merge($new_id, @old_ids);
    $self->c->model('ISRC')->merge_recordings($new_id, @old_ids);
    $self->c->model('Edit')->merge_entities('recording', $new_id, @old_ids);
    $self->c->model('Collection')->merge_entities('recording', $new_id, @old_ids);
    $self->c->model('Relationship')->merge_entities('recording', $new_id, \@old_ids);

    # Move tracks to the new recording
    $self->sql->do('UPDATE track SET recording = ?
              WHERE recording IN ('.placeholders(@old_ids).')', $new_id, @old_ids);

    merge_table_attributes(
        $self->sql => (
            table => 'recording',
            columns => [ qw( length ) ],
            old_ids => \@old_ids,
            new_id => $new_id
        )
    );

    merge_boolean_attributes(
        $self->sql => (
            table => 'recording',
            columns => [ qw( video ) ],
            old_ids => \@old_ids,
            new_id => $new_id
        )
    );

    $self->_delete_and_redirect_gids('recording', $new_id, @old_ids);
    return 1;
}

sub find_standalone
{
    my ($self, $artist_id, $limit, $offset) = @_;
    my $query ='
        SELECT DISTINCT ' . $self->_columns . ',
            recording.name COLLATE musicbrainz
          FROM ' . $self->_table . '
     LEFT JOIN track t ON t.recording = recording.id
          JOIN artist_credit_name acn
            ON acn.artist_credit = recording.artist_credit
         WHERE t.id IS NULL
           AND acn.artist = ?
      ORDER BY recording.name COLLATE musicbrainz';
    $self->query_to_list_limited($query, [$artist_id], $limit, $offset);
}

sub find_video
{
    my ($self, $artist_id, $limit, $offset) = @_;
    my $query ='
        SELECT DISTINCT ' . $self->_columns . ',
            recording.name COLLATE musicbrainz
          FROM ' . $self->_table . '
          JOIN artist_credit_name acn
            ON acn.artist_credit = recording.artist_credit
         WHERE video IS TRUE
           AND acn.artist = ?
      ORDER BY recording.name COLLATE musicbrainz';
    $self->query_to_list_limited($query, [$artist_id], $limit, $offset);
}
=method appears_on

This method will return a list of release groups the recordings appear
on. The results are ordered using the type-id (so albums come first,
then singles, etc..) and then by name.

=cut

sub appears_on
{
    my ($self, $recordings, $limit) = @_;

    return () unless scalar @$recordings;

    my @ids = map { $_->id } @$recordings;

    my $query =
        "SELECT DISTINCT ON (recording.id, rg.name, type)
             rg.id, rg.gid, type AS primary_type_id, rg.name,
             rg.artist_credit AS artist_credit_id, recording.id AS recording
         FROM release_group rg
           JOIN release ON release.release_group = rg.id
           JOIN medium ON release.id = medium.release
           JOIN track ON track.medium = medium.id
           JOIN recording ON recording.id = track.recording
         WHERE recording.id IN (" . placeholders (@ids) . ")";

    my %map;
    for my $row (@{ $self->sql->select_list_of_hashes($query, @ids) }) {
        my $recording_id = delete $row->{recording};
        $map{$recording_id} ||= [];
        push @{ $map{$recording_id} }, MusicBrainz::Server::Data::ReleaseGroup->_new_from_row($row);
    }

    for my $rec_id (keys %map)
    {
        # A crude ordering of importance.
        my @rgs = uniq_by { $_->name }
                  rev_nsort_by { $_->primary_type_id // -1 }
                  sort_by { $_->name  }
                  @{ $map{$rec_id} };

        $map{$rec_id} = {
            hits => scalar @rgs,
            results => scalar @rgs > $limit ? [ @rgs[ 0 .. ($limit-1) ] ] : \@rgs,
        }
    }

    return %map;
}

__PACKAGE__->meta->make_immutable;
no Moose;
1;

=head1 COPYRIGHT

Copyright (C) 2009 Lukas Lalinsky

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

=cut


/** -----------------------------------------------------------
  MEX file for computing a solution to the LSAP with the Hungarian algorithm

             [rho] = hungarianLSAP(C,init_type,forb)
      [rho,varrho] = hungarianLSAP(C,init_type,forb)
         [rho,u,v] = hungarianLSAP(C,init_type,forb)
  [rho,varrho,u,v] = hungarianLSAP(C,init_type,forb)

  Given a nxm cost matrix C (integer ou floatting values) it computes:

  - a solution rho to the LSAP, i.e. a one-to-one mapping from the rows of C to its columns,
    and the one-to-to mapping from the columns to the rows

    rho is represented by a nx1 matrix so that rho(i)=j means that i is assigned to j
    varrho is a 1xm matrix so that varrho(j)=i means that j is assigned to i
    for the asymmetric LSAP (n and m are not equal):
      if n<m:
         rho is an injection from {1,...,n} to {1,...,m}
         m-n columns are not assigned, which is represented by varrho(j)=-1
      if n>m
         varrho is an injection from {1,...,m} to {1,...,n}
         n-m rows are not assigned, which is represented by rho(i)=-1

  - a solution (u,v) to its dual problem (labeling problem)

  optional integer init_type:
  0 -> no initialization
  1 -> classical initialization u is the min of each row and v the min of each column minus u

  optional boolean parameter forb:
  - true  -> forbidden assignments are represented by negative cost values
  - false -> no forbidden assignments (by default)

  This is a MEX-file for MATLAB.

  This file is part of LSAPE.
  LSAPE is free software: you can redistribute it and/or modify it
  under the terms of the CeCILL-C License. See README for more details.

     Copyright 2015-2017
      authors: Sebastien Bougleux
  institution: Normandie Univ, CNRS - ENSICAEN - UNICAEN, GREYC, France
   last modif: July 5 2017

  execute matlab file 'compile_mex' to compile this function and use it in matlab
 *  -----------------------------------------------------------
*/

#include <mex.h>
#include <cstdio>
#include <string>
#include <hungarian-lsap.hh>
#include <utils.hh>

template <typename DT>
void hungarian_helper(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[], const mxClassID &mxC)
{
  // 1st input : edit cost matrix
  const DT *C = (DT*)mxGetPr(prhs[0]);
  // get dimensions
  int nrows = (int)mxGetDimensions(prhs[0])[0];
  int ncols = (int)mxGetDimensions(prhs[0])[1];
  int dimr2[2] = { nrows, 1 }, dimc2[2] = { 1, ncols };
  bool forbassign = false;
  unsigned short init_type = 1;
  if (nrhs > 1) init_type = (unsigned short)mxGetScalar(prhs[1]);
  if (nrhs == 3) forbassign = (bool)mxGetScalar(prhs[2]);
  //------------------------------------------------------------------
  int i = 0;
  plhs[0] = mxCreateNumericArray(2, dimr2, mxINT32_CLASS, mxREAL);
  int *rho = (int*)mxGetData(plhs[0]);
  int *varrho = NULL;
  if (nlhs == 2 || nlhs == 4)
  {
    plhs[1] = mxCreateNumericArray(2, dimc2, mxINT32_CLASS, mxREAL);
    varrho = (int*)mxGetData(plhs[1]);
  }
  DT *u = NULL, *v = NULL;
  if (nlhs > 2)
  {
    plhs[nlhs-2] = mxCreateNumericArray(2, dimr2, mxC, mxREAL);
    u = (DT*)mxGetPr(plhs[nlhs-2]);
    plhs[nlhs-1] = mxCreateNumericArray(2, dimc2, mxC, mxREAL);
    v = (DT*)mxGetPr(plhs[nlhs-1]);
  }
  else { u = new DT[nrows]; v = new DT[ncols];}
  hungarianLSAP<DT,int>(C,nrows,ncols,rho,u,v,varrho,init_type,forbassign);
  for (int i = 0; i < nrows; i++) rho[i]++;
  if (nlhs == 2 || nlhs == 4) for (int j = 0; j < ncols; j++) varrho[j]++;
  if (nlhs < 3) { delete[] u; delete[] v; }
}

//------------------------------------------------------------------
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  if (nrhs < 1 || nrhs > 3 || nlhs < 1 || nlhs > 4) mexErrMsgTxt("USAGE: [rho] = hungarianLSAP(C,init_type,forbassign)\nUSAGE: [rho,varrho] = hungarianLSAP(C,init_type,forbassign)\nUSAGE: [rho,u,v] = hungarianLSAP(C,init_type,forbassign)\nUSAGE: [rho,varrho,u,v] = hungarianLSAP(C,init_type,forbassign)\n");
  mxClassID tclass = mxGetClassID(prhs[0]);
  switch(tclass)
  {
    case mxINT16_CLASS: hungarian_helper<short>(nlhs,plhs,nrhs,prhs,tclass); break;
    case mxINT32_CLASS: hungarian_helper<int>(nlhs,plhs,nrhs,prhs,tclass); break;
    case mxINT64_CLASS: hungarian_helper<int64_T>(nlhs,plhs,nrhs,prhs,tclass); break;
    case mxSINGLE_CLASS: hungarian_helper<float>(nlhs,plhs,nrhs,prhs,tclass); break;
    default: hungarian_helper<double>(nlhs,plhs,nrhs,prhs,tclass);
  }
}


---

- name: "{{ test }}"
  hosts: debian
  become: true
  gather_facts: false
  tasks:

    # Latest
    - tags: [latest]
      block:
        - file:
            path: /usr/local/bin/symfony
            state: absent
        - import_role:
            name: symfony_cli
          vars:
            manala_symfony_cli_version: ~
      always:
        - name: Goss
          command: >
            goss --gossfile {{ test }}.goss.yml --vars-inline "{tags: [latest]}" validate

    # Version
    - tags: [version]
      block:
        - file:
            path: /usr/local/bin/symfony
            state: absent
        - import_role:
            name: symfony_cli
          vars:
            manala_symfony_cli_version: 4.16.0
      always:
        - name: Goss
          command: >
            goss --gossfile {{ test }}.goss.yml --vars-inline "{tags: [version]}" validate


/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

describe('promise it', () => {
  beforeEach(() => {
    this.someContextValue = 'value';
  });

  // passing tests
  it('passes a sync test', () => {
    expect(1).toBe(1);
  });

  it('waits for promise to be resolved', () => Promise.resolve());

  it('works with done', done => {
    done();
  });

  it('works with async done', done => {
    setTimeout(done, 1);
  });

  it('is bound to context object', () =>
    new Promise(resolve => {
      if (this.someContextValue !== 'value') {
        throw new Error(
          'expected this.someContextValue to be set: ' + this.someContextValue
        );
      }
      resolve();
    }));

  // failing tests
  it('fails if promise is rejected', () =>
    Promise.reject(new Error('rejected promise returned')));

  it('works with done.fail', done => {
    done.fail(new Error('done.fail was called'));
  });

  it('works with done(error)', done => {
    done(new Error('done was called with error'));
  });

  it('fails if failed expectation with done', done => {
    expect(true).toEqual(false);
    done();
  });

  it('fails if failed expectation with done - async', done => {
    setTimeout(() => {
      expect(true).toEqual(false);
      done();
    }, 1);
  });

  it('fails with thrown error with done - sync', done => {
    throw new Error('sync fail');
    done(); // eslint-disable-line
  });

  it('fails with thrown error with done - async', done => {
    setTimeout(() => {
      throw new Error('async fail');
      done(); // eslint-disable-line
    }, 1);
  });

  // I wish it was possible to catch this but I do not see a way.
  // Currently both jest and mocha will pass this test.
  it.skip('fails with thrown error - async', () => {
    setTimeout(() => {
      throw new Error('async fail - no done');
    }, 1);
  });

  it('fails a sync test', () => {
    expect('sync').toBe('failed');
  });

  it(
    'succeeds if the test finishes in time',
    () => new Promise(resolve => setTimeout(resolve, 10)),
    250
  );

  // failing tests
  it(
    'fails if a custom timeout is exceeded',
    () => new Promise(resolve => setTimeout(resolve, 100)),
    10
  );
});


/**
  ******************************************************************************
  * @file    stm32f7xx_hal_def.h
  * @author  MCD Application Team
  * @version V1.2.0
  * @date    30-December-2016
  * @brief   This file contains HAL common defines, enumeration, macros and
  *          structures definitions.
  ******************************************************************************
  * @attention
  *
  *
© COPYRIGHT(c) 2016 STMicroelectronics

  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F7xx_HAL_DEF
#define __STM32F7xx_HAL_DEF

#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f7xx.h"
//#include "Legacy/stm32_hal_legacy.h"
#include <stdio.h>
/* Exported types ------------------------------------------------------------*/

/**
  * @brief  HAL Status structures definition
  */
typedef enum
{
  HAL_OK       = 0x00U,
  HAL_ERROR    = 0x01U,
  HAL_BUSY     = 0x02U,
  HAL_TIMEOUT  = 0x03U
} HAL_StatusTypeDef;

/**
  * @brief  HAL Lock structures definition
  */
typedef enum
{
  HAL_UNLOCKED = 0x00,
  HAL_LOCKED   = 0x01
} HAL_LockTypeDef;

/* Exported macro ------------------------------------------------------------*/
#define HAL_MAX_DELAY      0xFFFFFFFFU

#define HAL_IS_BIT_SET(REG, BIT)         (((REG) & (BIT)) != RESET)
#define HAL_IS_BIT_CLR(REG, BIT)         (((REG) & (BIT)) == RESET)

#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__)               \
                        do{                                                      \
                              (__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
                              (__DMA_HANDLE__).Parent = (__HANDLE__);             \
                          } while(0)

//#define UNUSED(x) ((void)(x))

/** @brief Reset the Handle's State field.
  * @param __HANDLE__: specifies the Peripheral Handle.
  * @note  This macro can be used for the following purpose:
  *          - When the Handle is declared as local variable; before passing it as parameter
  *            to HAL_PPP_Init() for the first time, it is mandatory to use this macro
  *            to set to 0 the Handle's "State" field.
  *            Otherwise, "State" field may have any random value and the first time the function
  *            HAL_PPP_Init() is called, the low level hardware initialization will be missed
  *            (i.e. HAL_PPP_MspInit() will not be executed).
  *          - When there is a need to reconfigure the low level hardware: instead of calling
  *            HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init().
  *            In this later function, when the Handle's "State" field is set to 0, it will execute the function
  *            HAL_PPP_MspInit() which will reconfigure the low level hardware.
  * @retval None
  */
#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0U)

#if (USE_RTOS == 1)
  /* Reserved for future use */
  #error "USE_RTOS should be 0 in the current HAL release"
#else
  #define __HAL_LOCK(__HANDLE__)                                           \
                                do{                                        \
                                    if((__HANDLE__)->Lock == HAL_LOCKED)   \
                                    {                                      \
                                       return HAL_BUSY;                    \
                                    }                                      \
                                    else                                   \
                                    {                                      \
                                       (__HANDLE__)->Lock = HAL_LOCKED;    \
                                    }                                      \
                                  }while (0)

  #define __HAL_UNLOCK(__HANDLE__)                                          \
                                  do{                                       \
                                      (__HANDLE__)->Lock = HAL_UNLOCKED;    \
                                    }while (0)
#endif /* USE_RTOS */

#if  defined ( __GNUC__ )
  #ifndef __weak
    #define __weak   __attribute__((weak))
  #endif /* __weak */
  #ifndef __packed
    #define __packed __attribute__((__packed__))
  #endif /* __packed */
#endif /* __GNUC__ */

/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */
#if defined   (__GNUC__)        /* GNU Compiler */
  #ifndef __ALIGN_END
    #define __ALIGN_END    __attribute__ ((aligned (4)))
  #endif /* __ALIGN_END */
  #ifndef __ALIGN_BEGIN
    #define __ALIGN_BEGIN
  #endif /* __ALIGN_BEGIN */
#else
  #ifndef __ALIGN_END
    #define __ALIGN_END
  #endif /* __ALIGN_END */
  #ifndef __ALIGN_BEGIN
    #if defined   (__CC_ARM)      /* ARM Compiler */
      #define __ALIGN_BEGIN    __align(4)
    #elif defined (__ICCARM__)    /* IAR Compiler */
      #define __ALIGN_BEGIN
    #endif /* __CC_ARM */
  #endif /* __ALIGN_BEGIN */
#endif /* __GNUC__ */

/**
  * @brief  __RAM_FUNC definition
  */
#if defined ( __CC_ARM   )
/* ARM Compiler
   ------------
   RAM functions are defined using the toolchain options.
   Functions that are executed in RAM should reside in a separate source module.
   Using the 'Options for File' dialog you can simply change the 'Code / Const'
   area of a module to a memory space in physical RAM.
   Available memory areas are declared in the 'Target' tab of the 'Options for Target'
   dialog.
*/
#define __RAM_FUNC HAL_StatusTypeDef

#elif defined ( __ICCARM__ )
/* ICCARM Compiler
   ---------------
   RAM functions are defined using a specific toolchain keyword "__ramfunc".
*/
#define __RAM_FUNC __ramfunc HAL_StatusTypeDef

#elif defined   (  __GNUC__  )
/* GNU Compiler
   ------------
  RAM functions are defined using a specific toolchain attribute
   "__attribute__((section(".RamFunc")))".
*/
#define __RAM_FUNC HAL_StatusTypeDef  __attribute__((section(".RamFunc")))

#endif

/**
  * @brief  __NOINLINE definition
  */
#if defined ( __CC_ARM   ) || defined   (  __GNUC__  )
/* ARM & GNUCompiler
   ----------------
*/
#define __NOINLINE __attribute__ ( (noinline) )

#elif defined ( __ICCARM__ )
/* ICCARM Compiler
   ---------------
*/
#define __NOINLINE _Pragma("optimize = no_inline")

#endif

#ifdef __cplusplus
}
#endif

#endif /* ___STM32F7xx_HAL_DEF */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


py.test 2.2.0: test marking++, parametrization++ and duration profiling
===========================================================================

pytest-2.2.0 is a test-suite compatible release of the popular
py.test testing tool.  Plugins might need upgrades. It comes
with these improvements:

* easier and more powerful parametrization of tests:

  - new @pytest.mark.parametrize decorator to run tests with different arguments
  - new metafunc.parametrize() API for parametrizing arguments independently
  - see examples at http://pytest.org/latest/example/parametrize.html
  - NOTE that parametrize() related APIs are still a bit experimental
    and might change in future releases.

* improved handling of test markers and refined marking mechanism:

  - "-m markexpr" option for selecting tests according to their mark
  - a new "markers" ini-variable for registering test markers for your project
  - the new "--strict" bails out with an error if using unregistered markers.
  - see examples at http://pytest.org/latest/example/markers.html

* duration profiling: new "--duration=N" option showing the N slowest test
  execution or setup/teardown calls. This is most useful if you want to
  find out where your slowest test code is.

* also 2.2.0 performs more eager calling of teardown/finalizers functions
  resulting in better and more accurate reporting when they fail

Besides there is the usual set of bug fixes along with a cleanup of
pytest's own test suite allowing it to run on a wider range of environments.

For general information, see extensive docs with examples here:

     http://pytest.org/

If you want to install or upgrade pytest you might just type::

    pip install -U pytest # or
    easy_install -U pytest

Thanks to Ronny Pfannschmidt, David Burns, Jeff Donner, Daniel Nouri, Alfredo Deza and all who gave feedback or sent bug reports.

best,
holger krekel

notes on incompatibility
------------------------------

While test suites should work unchanged you might need to upgrade plugins:

* You need a new version of the pytest-xdist plugin (1.7) for distributing
  test runs.

* Other plugins might need an upgrade if they implement
  the ``pytest_runtest_logreport`` hook which now is called unconditionally
  for the setup/teardown fixture phases of a test. You may choose to
  ignore setup/teardown failures by inserting "if rep.when != 'call': return"
  or something similar. Note that most code probably "just" works because
  the hook was already called for failing setup/teardown phases of a test
  so a plugin should have been ready to grok such reports already.

Changes between 2.1.3 and 2.2.0
----------------------------------------

- fix issue90: introduce eager tearing down of test items so that
  teardown function are called earlier.
- add an all-powerful metafunc.parametrize function which allows to
  parametrize test function arguments in multiple steps and therefore
  from independent plugins and places.
- add a @pytest.mark.parametrize helper which allows to easily
  call a test function with different argument values.
- Add examples to the "parametrize" example page, including a quick port
  of Test scenarios and the new parametrize function and decorator.
- introduce registration for "pytest.mark.*" helpers via ini-files
  or through plugin hooks.  Also introduce a "--strict" option which
  will treat unregistered markers as errors
  allowing to avoid typos and maintain a well described set of markers
  for your test suite.  See examples at http://pytest.org/latest/mark.html
  and its links.
- issue50: introduce "-m marker" option to select tests based on markers
  (this is a stricter and more predictable version of "-k" in that "-m"
  only matches complete markers and has more obvious rules for and/or
  semantics.
- new feature to help optimizing the speed of your tests:
  --durations=N option for displaying N slowest test calls
  and setup/teardown methods.
- fix issue87: --pastebin now works with python3
- fix issue89: --pdb with unexpected exceptions in doctest work more sensibly
- fix and cleanup pytest's own test suite to not leak FDs
- fix issue83: link to generated funcarg list
- fix issue74: pyarg module names are now checked against imp.find_module false positives
- fix compatibility with twisted/trial-11.1.0 use cases


name=Voice of Grace
image=https://magiccards.info/scans/en/us/54.jpg
value=3.257
rarity=U
type=Creature
subtype=Angel
cost={3}{W}
pt=2/2
ability=Flying, protection from black
timing=main
oracle=Flying, protection from black


// SPDX-License-Identifier: GPL-2.0+
/*
 * NXP ls1012a 2G5RDB board device tree source
 *
 * Copyright 2017 NXP
 */

/dts-v1/;
#include "fsl-ls1012a.dtsi"

/ {
	model = "LS1012A 2G5RDB Board";

	aliases {
		spi0 = &qspi;
	};

	chosen {
		stdout-path = &duart0;
	};
};

&qspi {
	bus-num = <0>;
	status = "okay";

	qflash0: s25fl128s@0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "jedec,spi-nor";
		spi-max-frequency = <20000000>;
		reg = <0>;
	};
};

&i2c0 {
	status = "okay";
};

&duart0 {
	status = "okay";
};

&sata {
	status = "okay";
};


package org.jboss.weld.tests.producer.method.broken.invalidBeanType;

import jakarta.enterprise.inject.Produces;

/**
* @author Marko Luksa
*/
public class MultiDimensionalWildcardTypeArrayProducer {
    @Produces
    public Foo<?>[][][] produceWildcardFooArray() {
        return null;
    }
}


/* No comment */
"Listing directory {0} failed" = "Pridobitev seznama vsebine imenika ni uspela {0}";

/* Touch file failed */
"Cannot create {0}" = "Datoteke ni mogoče ustvariti {0}";

/* Create directory failed */
"Cannot create folder {0}" = "Mape ni mogoče ustvariti {0}";

/* Moving file failed */
"Cannot rename {0}" = "Datoteke ni mogoče preimenovati {0}";

/* Reading metadata of file failed */
"Failure to read attributes of {0}" = "Atributov datoteke ni mogoče prebrati";

/* Writing metadata of file failed */
"Failure to write attributes of {0}" = "Atributov datoteke ni mogoče zapisati";

/* Removing file failed */
"Cannot delete {0}" = "Datoteke ni mogoče izbrisati {0}";

/* Ownership of file */
"Cannot change owner" = "Lastnika ni mogoče spremeniti";

/* Group ownership of file or folder */
"Cannot change group" = "Skupine ni mogoče spremeniti";

/* Fails to change UNIX access permissions */
"Cannot change permissions of {0}" = "Dovoljenj ni mogoče spremeniti";
"Cannot change timestamp of {0}" = "Časovnega žiga ni mogoče spremeniti";

/* Mount failure */
"Connection failed" = "Povezava ni uspela";

/* Transfer failure */
"Download {0} failed" = "Prenos ni uspel";

/* Transfer failure */
"Upload {0} failed" = "Prenos na strežnik ni uspel";

/* Content distribution network configuration failures */
"Cannot read CDN configuration" = "CDN konfiguracije ni mogoče prebrati";
"Cannot write CDN configuration" = "CDN konfiguracije ni mogoče zapisati";

/* Container configuration such as logging or versioning */
"Cannot read container configuration" = "Vsebnikove konfiguracije ni mogoče prebrati";

"Interoperability failure" = "Interoperability failure";
"Access denied" = "Access denied";
"File not found" = "File not found";
"Insufficient disk space" = "Insufficient disk space";

"DNS lookup for {0} failed" = "DNS lookup for {0} failed";

"Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server" = "Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server";


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="1.0" toolsVersion="1906" systemVersion="11A511" targetRuntime="iOS.CocoaTouch.iPad" nextObjectID="6" propertyAccessControl="none" initialViewController="2">
    <dependencies>
        <development defaultVersion="4200" identifier="xcode"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="902"/>
    </dependencies>
    <scenes>
        <scene sceneID="4">
            <objects>
                <placeholder placeholderIdentifier="IBFirstResponder" id="3" sceneMemberID="firstResponder"/>
                <viewController id="2" customClass="ViewController" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="5">
                        <rect key="frame" x="0.0" y="20" width="768" height="1004"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                </viewController>
            </objects>
        </scene>
    </scenes>
    <simulatedMetricsContainer key="defaultSimulatedMetrics">
        <simulatedStatusBarMetrics key="statusBar" statusBarStyle="blackTranslucent"/>
        <simulatedOrientationMetrics key="orientation"/>
        <simulatedScreenMetrics key="destination"/>
    </simulatedMetricsContainer>
</document>


<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item>
    <item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item>
    <item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item>
    <item name="ic_menu_manage" type="drawable">@android:drawable/ic_menu_manage</item>
    <item name="ic_menu_share" type="drawable">@android:drawable/ic_menu_share</item>
    <item name="ic_menu_send" type="drawable">@android:drawable/ic_menu_send</item>
</resources>


class ForSomeVsUnapply {
  def test: Unit = {
    def makeWrap: Wrap = ???
    def useRep[e](rep: (e, X[e])) = ()

    val repUnapply = Wrap.unapply(makeWrap).get
    useRep(repUnapply)  // okay

    val Wrap(rep0) = makeWrap
    useRep(rep0) // error

    val rep = makeWrap match {
      case Wrap(r) => r
    };

    useRep(rep) // error
  }
}

class X[e]

case class Wrap(rep: (e, X[e]) forSome { type e })


/*
 *
 * Copyright 2014 gRPC authors.
 *
 * 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.
 *
 */

package grpc

import (
	"google.golang.org/grpc/encoding"
	_ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
)

// baseCodec contains the functionality of both Codec and encoding.Codec, but
// omits the name/string, which vary between the two and are not needed for
// anything besides the registry in the encoding package.
type baseCodec interface {
	Marshal(v interface{}) ([]byte, error)
	Unmarshal(data []byte, v interface{}) error
}

var _ baseCodec = Codec(nil)
var _ baseCodec = encoding.Codec(nil)

// Codec defines the interface gRPC uses to encode and decode messages.
// Note that implementations of this interface must be thread safe;
// a Codec's methods can be called from concurrent goroutines.
//
// Deprecated: use encoding.Codec instead.
type Codec interface {
	// Marshal returns the wire format of v.
	Marshal(v interface{}) ([]byte, error)
	// Unmarshal parses the wire format into v.
	Unmarshal(data []byte, v interface{}) error
	// String returns the name of the Codec implementation.  This is unused by
	// gRPC.
	String() string
}


/*
 * ASort() function
 *
 * Copyright 1999-2001 Viktor Szakats (vszakats.net/harbour)
 * Copyright 1999-2001 Jose Lalin <dezac@corevia.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file LICENSE.txt.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
 *
 * As a special exception, the Harbour Project gives permission for
 * additional uses of the text contained in its release of Harbour.
 *
 * The exception is that, if you link the Harbour libraries with other
 * files to produce an executable, this does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * Your use of that executable is in no way restricted on account of
 * linking the Harbour library code into it.
 *
 * This exception does not however invalidate any other reasons why
 * the executable file might be covered by the GNU General Public License.
 *
 * This exception applies only to the code released by the Harbour
 * Project under the name Harbour.  If you copy code from other
 * Harbour Project or Free Software Foundation releases into a copy of
 * Harbour, as the General Public License permits, the exception does
 * not apply to the code that you add in this way.  To avoid misleading
 * anyone as to the status of such modified files, you must delete
 * this exception notice from them.
 *
 * If you write modifications of your own for Harbour, it is your choice
 * whether to permit this exception to apply to your modifications.
 * If you do not wish that, delete this exception notice.
 *
 */

/* FIXME: The sorting engine requires signed indexes to work, this means
          that arrays larger than 2^31 elements cannot be sorted. [vszakats] */

/* NOTE: Based on PD code found in
         SORTING AND SEARCHING ALGORITHMS: A COOKBOOK, BY THOMAS NIEMANN
         https://www.cs.auckland.ac.nz/~jmor159/PLDS210/niemann/s_man.htm */

#include "hbvmint.h"
#include "hbapiitm.h"
#include "hbvm.h"

static HB_BOOL hb_itemIsLess( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
                              HB_SIZE nItem1, HB_SIZE nItem2 )
{
   PHB_ITEM pItem1 = pBaseArray->pItems + nItem1,
            pItem2 = pBaseArray->pItems + nItem2;

   if( pBlock )
   {
      PHB_ITEM pRet;

      /* protection against array resizing by user codeblock */
      if( pBaseArray->nLen <= nItem1 || pBaseArray->nLen <= nItem2 )
         return HB_FALSE;

      hb_vmPushEvalSym();
      hb_vmPush( pBlock );
      hb_vmPush( pItem1 );
      hb_vmPush( pItem2 );
      hb_vmSend( 2 );

      pRet = hb_param( -1, HB_IT_ANY );

      /* CA-Cl*pper always takes return value as logical item
       * accepting 0, 1 as numeric representation of HB_FALSE/HB_TRUE
       */
      return ( HB_IS_LOGICAL( pRet ) || HB_IS_NUMERIC( pRet ) ) ?
             hb_itemGetL( pRet ) : HB_TRUE;
   }

   /* Do native compare when no codeblock is supplied */

   if( HB_IS_STRING( pItem1 ) && HB_IS_STRING( pItem2 ) )
      return hb_itemStrCmp( pItem1, pItem2, HB_FALSE ) < 0;
   else if( HB_IS_NUMINT( pItem1 ) && HB_IS_NUMINT( pItem2 ) )
      /* intentionally separate comparison for integer numbers
         to avoid precision lose in 64-bit integer to double conversion */
      return hb_itemGetNInt( pItem1 ) < hb_itemGetNInt( pItem2 );
   else if( HB_IS_NUMERIC( pItem1 ) && HB_IS_NUMERIC( pItem2 ) )
      return hb_itemGetND( pItem1 ) < hb_itemGetND( pItem2 );
   else if( HB_IS_TIMESTAMP( pItem1 ) && HB_IS_TIMESTAMP( pItem2 ) )
   {
      long lDate1, lTime1, lDate2, lTime2;

      hb_itemGetTDT( pItem1, &lDate1, &lTime1 );
      hb_itemGetTDT( pItem2, &lDate2, &lTime2 );
      return lDate1 == lDate2 ? lTime1 < lTime2 : lDate1 < lDate2;
   }
   else if( HB_IS_DATETIME( pItem1 ) && HB_IS_DATETIME( pItem2 ) )
      /* it's not exact comparison, compare only Julian date */
      return hb_itemGetDL( pItem1 ) < hb_itemGetDL( pItem2 );
   else if( HB_IS_LOGICAL( pItem1 ) && HB_IS_LOGICAL( pItem2 ) )
      return hb_itemGetL( pItem1 ) < hb_itemGetL( pItem2 );
   else
   {
      /* NOTE: For non-matching types CA-Cl*pper sorts always like this:
               Array/Object Block String Logical Date Numeric NIL [jlalin] */

      int iWeight1;
      int iWeight2;

      if( HB_IS_ARRAY( pItem1 ) ) iWeight1 = 1;
      else if( HB_IS_BLOCK( pItem1 ) ) iWeight1 = 2;
      else if( HB_IS_STRING( pItem1 ) ) iWeight1 = 3;
      else if( HB_IS_LOGICAL( pItem1 ) ) iWeight1 = 4;
      else if( HB_IS_DATETIME( pItem1 ) ) iWeight1 = 5;
      else if( HB_IS_NUMERIC( pItem1 ) ) iWeight1 = 6;
      else iWeight1 = 7;

      if( HB_IS_ARRAY( pItem2 ) ) iWeight2 = 1;
      else if( HB_IS_BLOCK( pItem2 ) ) iWeight2 = 2;
      else if( HB_IS_STRING( pItem2 ) ) iWeight2 = 3;
      else if( HB_IS_LOGICAL( pItem2 ) ) iWeight2 = 4;
      else if( HB_IS_DATETIME( pItem2 ) ) iWeight2 = 5;
      else if( HB_IS_NUMERIC( pItem2 ) ) iWeight2 = 6;
      else iWeight2 = 7;

      return iWeight1 < iWeight2;
   }
}

#ifdef HB_CLP_STRICT

/* partition array pItems[lb..ub] */

static HB_ISIZ hb_arraySortQuickPartition( PHB_BASEARRAY pBaseArray, HB_ISIZ lb, HB_ISIZ ub, PHB_ITEM pBlock )
{
   HB_ISIZ i, j;

   /* select pivot and exchange with 1st element */
   i = lb + ( ( ub - lb ) >> 1 );
   if( i != lb )
      hb_itemRawSwap( pBaseArray->pItems + lb, pBaseArray->pItems + i );

   /* sort lb+1..ub based on pivot */
   i = lb + 1;
   j = ub;

   for( ;; )
   {
      while( i < j && hb_itemIsLess( pBaseArray, pBlock, i, lb ) )
         i++;

      while( j >= i && hb_itemIsLess( pBaseArray, pBlock, lb, j ) )
         j--;

      if( i >= j )
         break;

      /* Swap the items */
      hb_itemRawSwap( pBaseArray->pItems + i, pBaseArray->pItems + j );
      j--;
      i++;
   }

   /* pivot belongs in pBaseArray->pItems[ j ] */
   if( j > lb && pBaseArray->nLen > ( HB_SIZE ) j )
      hb_itemRawSwap( pBaseArray->pItems + lb, pBaseArray->pItems + j );

   return j;
}

/* sort array pBaseArray->pItems[lb..ub] */

static void hb_arraySortQuick( PHB_BASEARRAY pBaseArray, HB_ISIZ lb, HB_ISIZ ub, PHB_ITEM pBlock )
{
   while( lb < ub )
   {
      HB_ISIZ m;

      if( ( HB_SIZE ) ub >= pBaseArray->nLen )
      {
         ub = pBaseArray->nLen - 1;
         if( lb >= ub )
            break;
      }

      /* partition into two segments */
      m = hb_arraySortQuickPartition( pBaseArray, lb, ub, pBlock );

      /* sort the smallest partition to minimize stack requirements */
      if( m - lb <= ub - m )
      {
         hb_arraySortQuick( pBaseArray, lb, m - 1, pBlock );
         lb = m + 1;
      }
      else
      {
         hb_arraySortQuick( pBaseArray, m + 1, ub, pBlock );
         ub = m - 1;
      }
   }
}

static void hb_arraySortStart( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
                               HB_SIZE nStart, HB_SIZE nCount )
{
   hb_arraySortQuick( pBaseArray, nStart, nStart + nCount - 1, pBlock );
}

#else

static HB_BOOL hb_arraySortDO( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
                               HB_SIZE * pSrc, HB_SIZE * pBuf, HB_SIZE nCount )
{
   if( nCount > 1 )
   {
      HB_SIZE nCnt1, nCnt2, * pPtr1, * pPtr2, * pDst;
      HB_BOOL fBuf1, fBuf2;

      nCnt1 = nCount >> 1;
      nCnt2 = nCount - nCnt1;
      pPtr1 = &pSrc[ 0 ];
      pPtr2 = &pSrc[ nCnt1 ];

      fBuf1 = hb_arraySortDO( pBaseArray, pBlock, pPtr1, &pBuf[ 0 ], nCnt1 );
      fBuf2 = hb_arraySortDO( pBaseArray, pBlock, pPtr2, &pBuf[ nCnt1 ], nCnt2 );
      if( fBuf1 )
         pDst = pBuf;
      else
      {
         pDst = pSrc;
         pPtr1 = &pBuf[ 0 ];
      }
      if( ! fBuf2 )
         pPtr2 = &pBuf[ nCnt1 ];

      while( nCnt1 > 0 && nCnt2 > 0 )
      {
         if( hb_itemIsLess( pBaseArray, pBlock, *pPtr2, *pPtr1 ) )
         {
            *pDst++ = *pPtr2++;
            nCnt2--;
         }
         else
         {
            *pDst++ = *pPtr1++;
            nCnt1--;
         }
      }
      if( nCnt1 > 0 )
      {
         do
            *pDst++ = *pPtr1++;
         while( --nCnt1 );
      }
      else if( nCnt2 > 0 && fBuf1 == fBuf2 )
      {
         do
            *pDst++ = *pPtr2++;
         while( --nCnt2 );
      }
      return ! fBuf1;
   }
   return HB_TRUE;
}

static void hb_arraySortStart( PHB_BASEARRAY pBaseArray, PHB_ITEM pBlock,
                               HB_SIZE nStart, HB_SIZE nCount )
{
   HB_SIZE * pBuffer, * pDest, * pPos, nPos, nTo;

   pBuffer = ( HB_SIZE * ) hb_xgrab( sizeof( HB_SIZE ) * 2 * nCount );
   for( nPos = 0; nPos < nCount; ++nPos )
      pBuffer[ nPos ] = nStart + nPos;

   if( hb_arraySortDO( pBaseArray, pBlock, pBuffer, &pBuffer[ nCount ], nCount ) )
      pPos = ( pDest = pBuffer ) + nCount;
   else
      pDest = ( pPos = pBuffer ) + nCount;

   /* protection against array resizing by user codeblock */
   if( nStart + nCount > pBaseArray->nLen )
   {
      if( pBaseArray->nLen > nStart )
      {
         for( nPos = nTo = 0; nPos < nCount; ++nPos )
         {
            if( pDest[ nPos ] < pBaseArray->nLen )
               pDest[ nTo++ ] = pDest[ nPos ];
         }
         nCount = nTo;
      }
      else
         nCount = 0;
   }

   for( nPos = 0; nPos < nCount; ++nPos )
      pPos[ pDest[ nPos ] - nStart ] = nPos;

   for( nPos = 0; nPos < nCount; ++nPos )
   {
      if( nPos + nStart != pDest[ nPos ] )
      {
         hb_itemRawSwap( pBaseArray->pItems + nPos + nStart,
                         pBaseArray->pItems + pDest[ nPos ] );
         pDest[ pPos[ nPos ] ] = pDest[ nPos ];
         pPos[ pDest[ nPos ] - nStart ] = pPos[ nPos ];
      }
   }

   hb_xfree( pBuffer );
}
#endif /* HB_CLP_STRICT */

HB_BOOL hb_arraySort( PHB_ITEM pArray, HB_SIZE * pnStart, HB_SIZE * pnCount, PHB_ITEM pBlock )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_arraySort(%p, %p, %p, %p)", ( void * ) pArray, ( void * ) pnStart, ( void * ) pnCount, ( void * ) pBlock ) );

   if( HB_IS_ARRAY( pArray ) )
   {
      PHB_BASEARRAY pBaseArray = pArray->item.asArray.value;
      HB_SIZE nLen = pBaseArray->nLen;
      HB_SIZE nStart;

      if( pnStart && *pnStart >= 1 )
         nStart = *pnStart;
      else
         nStart = 1;

      if( nStart <= nLen )
      {
         HB_SIZE nCount;

         if( pnCount && *pnCount >= 1 && ( *pnCount <= nLen - nStart ) )
            nCount = *pnCount;
         else
            nCount = nLen - nStart + 1;

         if( nStart + nCount > nLen )             /* check range */
            nCount = nLen - nStart + 1;

         /* Optimize when only one or no element is to be sorted */
         if( nCount > 1 )
            hb_arraySortStart( pBaseArray, pBlock, nStart - 1, nCount );
      }

      return HB_TRUE;
   }
   else
      return HB_FALSE;
}

HB_FUNC( ASORT )
{
   PHB_ITEM pArray = hb_param( 1, HB_IT_ARRAY );

   if( pArray && ! hb_arrayIsObject( pArray ) )
   {
      HB_SIZE nStart = hb_parns( 2 );
      HB_SIZE nCount = hb_parns( 3 );

      hb_arraySort( pArray,
                    HB_ISNUM( 2 ) ? &nStart : NULL,
                    HB_ISNUM( 3 ) ? &nCount : NULL,
                    hb_param( 4, HB_IT_EVALITEM ) );

      hb_itemReturn( pArray ); /* ASort() returns the array itself */
   }
}


/**
 * A specialized version of `_.every` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if all elements pass the predicate check,
 *  else `false`.
 */
function arrayEvery(array, predicate) {
  var index = -1,
      length = array.length;

  while (++index < length) {
    if (!predicate(array[index], index, array)) {
      return false;
    }
  }
  return true;
}

module.exports = arrayEvery;


p, h1, h2, h3, h4, h5, h6, hgroup, aside, div, section, article, blockquote, address, pre, figure {display: block; padding-top: 10px; border: 1px dashed #BBB; background: transparent no-repeat}
p, h1, h2, h3, h4, h5, h6, hgroup, aside, div, section, article, address, pre, figure {margin-left: 3px}
section, article, address, hgroup, aside, figure {margin: 0 0 1em 3px}

p {background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7)}
h1 {background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==)}
h2 {background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==)}
h3 {background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7)}
h4 {background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==)}
h5 {background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==)}
h6 {background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==)}
div {background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7)}
section {background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=)}
article {background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7)}
blockquote {background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7)}
address {background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=)}
pre {background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==)}
hgroup {background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7)}
aside {background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=)}
figure {background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7)}
figcaption {border: 1px dashed #BBB}


---
layout: default
title: Scalatron Troubleshooting
subtitle: Organizer Documentation
---

# About Scalatron

Scalatron is an educational resource for groups of programmers that want to learn more about
the Scala programming language or want to hone their Scala programming skills. It is based on
Scalatron BotWar, a competitive multi-player programming game in which coders pit bot programs
(written in Scala) against each other.

The documentation, tutorial and source code are intended as a community resource and are
in the public domain. Feel free to use, copy, and improve them!

# Summary

A lot of things can go wrong in life, and running Scalatron is one of them. Whatever happens,
though, you're probably not the only one experiencing it and so there's hope that by collecting
problematic experiences and solutions some of your pain can be alleviated. Here is a list of
things known to go wrong with Scalatron, and sometimes how to fix them:

## Problems Starting The Server

**On Windows, double-clicking `/bin/Scalatron.jar` pops up an error dialog "Could not find the main class. Program will exit."**

Probable Cause:

* Very likely your Java Runtime Environment is too old.
* Scalatron requires Version 1.6 or newer is required.

Steps to Solve:

* Go to [the Java download site](http://www.java.com/download/)
* Download a more recent Java Runtime Environment
* Install it and try again.

**On Windows, running `java -jar /bin/Scalatron.jar` displays a "UnsupportedClassVersionError"**

Probable Cause:

* Very likely your Java Runtime Environment is too old.
* Scalatron requires Version 1.6 or newer is required.

Steps to Solve:

* Go to [the Java download site](http://www.java.com/download/)
* Download a more recent Java Runtime Environment
* Install it and try again.

## Performance Problems

**Server hangs intermittently**

Probable Cause:

* Very likely Java has too little memory and spends too much time running garbage collection.

Steps to Solve:

* give the Scalatron server more memory - as much as you can, in fact. Try starting it with the following options:

    java -Xmx2G -server -jar Scalatron.jar

**Compilations are slow or time out**

Probable Cause:

* The load on the server is too high, causing compilations to take too long.
* This generally means that the ratio of users and bots to available CPU cycles is too high.

Steps to Solve:

* Run the server on a computer with more and/or faster CPU cores. Scalatron will use as many cores as you can provide.
* Ask users to write better-behaved bots - they should not spawn mini-bots with abandon.
* Spread your users across two servers, using one as a testing server (for frequent compilations) and
  one as a tournament server (for competitive runs of debugged bots).
* Provide more memory to the Scalatron server (see tips for "Server hangs intermittently").
* Throttle the simulation using the `-maxfps` command line option, e.g. using `maxfps 20'.
  This will keep the simulator from eating up all available CPU cycles.

## Problems Using The Browser Client

The following browser/platform combinations should work:

* Firefox 12.0 on Windows XP
* Firefox 12.0 on MacOS 10.6.8
* Safari 5.1.5 on MacOS 10.6.8

The following browser/platform combinations are known not to work:

* Internet Explorer 8 on Windows XP
* Internet Explorer 7 on Windows XP
* Firefox 2.0.0.11 on Windows XP


/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

CLASS({
  package: 'com.google.mail',
  name: 'MailClient',
  extends: 'foam.browser.ui.BrowserView',
  requires: [
    'foam.mlang.CannedQuery',
    'com.google.mail.EMailCitationView2',
    'com.google.mail.EMailView2',
    'foam.core.dao.AuthenticatedWebSocketDAO',
    'foam.lib.email.EMail',
    'foam.dao.EasyDAO',
    'com.google.mail.AuthClient',
    'foam.browser.BrowserConfig'
  ],
  properties: [
    {
      name: 'auth',
      factory: function() {
        return this.AuthClient.create({
          clientId: '406725352531-5500665qnpni7257ml84e33smke2ijjd.apps.googleusercontent.com',
          scopes: [
            "openid",
            "profile",
            "email",
            "https://www.googleapis.com/auth/gmail.modify",
            "https://www.googleapis.com/auth/gmail.compose"
          ]
        });
      }
    },
    {
      name: 'emailDAOContext',
      factory: function() {
        var Y = this.Y.sub();

        Y.registerModel({
          __proto__: this.AuthenticatedWebSocketDAO.__proto__,
          create: this.makeWebSocketDAO.bind(this)
        }, 'foam.core.dao.WebSocketDAO');
      }
    },
    {
      name: 'emailDAO',
      factory: function() {
        return this.EasyDAO.create({
          model: this.EMail,
          daoType: 'MDAO',
          guid: true,
          cloning: true,
          contextualize: true,
          syncWithServer: true,
          sockets: true
        });
      }
    },
    {
      name: 'cannedQueryDAO',
      factory: function() {
        var dao = this.EasyDAO.create({
          model: this.CannedQuery,
          seqNo: true,
          daoType: 'MDAO'
        });

        [
          this.CannedQuery.create({
            label: "Inbox",
            order: 1,
            expression: CONTAINS(this.EMail.LABELS, 'INBOX')
          }),
          this.CannedQuery.create({
            label: "All Mail",
            order: 2,
            expression: NOT(OR(
              CONTAINS(this.EMail.LABELS, 'SPAM'),
              CONTAINS(this.EMail.LABELS, 'TRASH'),
              CONTAINS(this.EMail.LABELS, 'SENT')))
          }),
          this.CannedQuery.create({
            label: "Starred",
            order: 3,
            expression: CONTAINS(this.EMail.LABELS, 'STARRED')
          })
        ].select(dao);

        return dao;
      }
    },
    {
      name: 'data',
      factory: function() {
        return this.BrowserConfig.create({
          title: 'GMail Lite',
          model: this.EMail,
          dao: this.emailDAO,
          cannedQueryDAO: this.cannedQueryDAO,
          listView: {
            factory_: 'foam.ui.DAOListView',
            rowView: 'com.google.mail.EMailCitationView2',
            minWidth: 350,
            preferredWidth: 500,
            maxWidth: 500
          },
          innerDetailView: 'com.google.mail.EMailView2'
        });
      }
    }
  ],
  methods: [
    function init() {
      this.SUPER();
      this.auth.go();
    },
    function makeWebSocketDAO(args, X) {
      var dao = this.AuthenticatedWebSocketDAO.create(args, X);
      Events.follow(dao.authToken$, this.auth.idToken$);
      return dao;
    }
  ]
});


/*
 Copyright (c) 2018, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_VEHICLE_INFO_PLUGIN_INCLUDE_VEHICLE_INFO_PLUGIN_VEHICLE_INFO_HMI_COMMAND_FACTORY_H
#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_VEHICLE_INFO_PLUGIN_INCLUDE_VEHICLE_INFO_PLUGIN_VEHICLE_INFO_HMI_COMMAND_FACTORY_H

#include "application_manager/application_manager.h"
#include "application_manager/command_factory.h"
#include "vehicle_info_plugin/custom_vehicle_data_manager.h"

namespace vehicle_info_plugin {
namespace app_mngr = application_manager;

/**
 * @brief The vehicle info hmi command factory.
 */
class VehicleInfoHmiCommandFactory : public app_mngr::CommandFactory {
 public:
  VehicleInfoHmiCommandFactory(
      app_mngr::ApplicationManager& application_manager,
      app_mngr::rpc_service::RPCService& rpc_service,
      app_mngr::HMICapabilities& hmi_capabilities,
      policy::PolicyHandlerInterface& policy_handler,
      CustomVehicleDataManager& custom_vehicle_data_manager);

  app_mngr::CommandSharedPtr CreateCommand(
      const app_mngr::commands::MessageSharedPtr& message,
      app_mngr::commands::Command::CommandSource source) OVERRIDE;

  bool IsAbleToProcess(
      const int32_t function_id,
      const app_mngr::commands::Command::CommandSource source) const OVERRIDE;

 private:
  app_mngr::ApplicationManager& application_manager_;
  app_mngr::rpc_service::RPCService& rpc_service_;
  app_mngr::HMICapabilities& hmi_capabilities_;
  policy::PolicyHandlerInterface& policy_handler_;
  CustomVehicleDataManager& custom_vehicle_data_manager_;

  app_mngr::CommandCreator& buildCommandCreator(
      const int32_t function_id, const int32_t message_type) const;

  DISALLOW_COPY_AND_ASSIGN(VehicleInfoHmiCommandFactory);
};
}  // namespace vehicle_info_plugin

#endif  // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_VEHICLE_INFO_PLUGIN_INCLUDE_VEHICLE_INFO_PLUGIN_VEHICLE_INFO_HMI_COMMAND_FACTORY_H