text:
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "system_preferences.h"
#include "SkColorPriv.h"
#include "SkData.h"
#include "SkDeferredCanvas.h"
#include "SkDevice.h"
#include "SkGPipe.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkPicture.h"
#include "SkRefCnt.h"
#include "SkStream.h"
#include "SkTArray.h"
#include "SamplePipeControllers.h"

#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
#include "GrRenderTarget.h"
#include "SkGpuDevice.h"
#include "SkGpuCanvas.h"
typedef GrContextFactory::GLContextType GLContextType;
#else
class GrContext;
class GrRenderTarget;
typedef int GLContextType;
#endif

static bool gForceBWtext;

extern bool gSkSuppressFontCachePurgeSpew;

#ifdef SK_SUPPORT_PDF
    #include "SkPDFDevice.h"
    #include "SkPDFDocument.h"
#endif

// Until we resolve http://code.google.com/p/skia/issues/detail?id=455 ,
// stop writing out XPS-format image baselines in gm.
#undef SK_SUPPORT_XPS
#ifdef SK_SUPPORT_XPS
    #include "SkXPSDevice.h"
#endif

#ifdef SK_BUILD_FOR_MAC
    #include "SkCGUtils.h"
    #define CAN_IMAGE_PDF   1
#else
    #define CAN_IMAGE_PDF   0
#endif

typedef int ErrorBitfield;
const static ErrorBitfield ERROR_NONE                    = 0x00;
const static ErrorBitfield ERROR_NO_GPU_CONTEXT          = 0x01;
const static ErrorBitfield ERROR_PIXEL_MISMATCH          = 0x02;
const static ErrorBitfield ERROR_DIMENSION_MISMATCH      = 0x04;
const static ErrorBitfield ERROR_READING_REFERENCE_IMAGE = 0x08;
const static ErrorBitfield ERROR_WRITING_REFERENCE_IMAGE = 0x10;

// If true, emit a messange when we can't find a reference image to compare
static bool gNotifyMissingReadReference;

using namespace skiagm;

class Iter {
public:
    Iter() {
        this->reset();
    }

    void reset() {
        fReg = GMRegistry::Head();
    }

    GM* next() {
        if (fReg) {
            GMRegistry::Factory fact = fReg->factory();
            fReg = fReg->next();
            return fact(0);
        }
        return NULL;
    }

    static int Count() {
        const GMRegistry* reg = GMRegistry::Head();
        int count = 0;
        while (reg) {
            count += 1;
            reg = reg->next();
        }
        return count;
    }

private:
    const GMRegistry* fReg;
};

static SkString make_name(const char shortName[], const char configName[]) {
    SkString name(shortName);
    name.appendf("_%s", configName);
    return name;
}

static SkString make_filename(const char path[],
                              const char pathSuffix[],
                              const SkString& name,
                              const char suffix[]) {
    SkString filename(path);
    if (filename.endsWith("/")) {
        filename.remove(filename.size() - 1, 1);
    }
    filename.append(pathSuffix);
    filename.append("/");
    filename.appendf("%s.%s", name.c_str(), suffix);
    return filename;
}

/* since PNG insists on unpremultiplying our alpha, we take no precision chances
    and force all pixels to be 100% opaque, otherwise on compare we may not get
    a perfect match.
 */
static void force_all_opaque(const SkBitmap& bitmap) {
    SkAutoLockPixels lock(bitmap);
    for (int y = 0; y < bitmap.height(); y++) {
        for (int x = 0; x < bitmap.width(); x++) {
            *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
        }
    }
}

static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
    SkBitmap copy;
    bitmap.copyTo(&copy, SkBitmap::kARGB_8888_Config);
    force_all_opaque(copy);
    return SkImageEncoder::EncodeFile(path.c_str(), copy,
                                      SkImageEncoder::kPNG_Type, 100);
}

static inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) {
    int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
    int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
    int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
    return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
}

static void compute_diff(const SkBitmap& target, const SkBitmap& base,
                         SkBitmap* diff) {
    SkAutoLockPixels alp(*diff);

    const int w = target.width();
    const int h = target.height();
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            SkPMColor c0 = *base.getAddr32(x, y);
            SkPMColor c1 = *target.getAddr32(x, y);
            SkPMColor d = 0;
            if (c0 != c1) {
                d = compute_diff_pmcolor(c0, c1);
            }
            *diff->getAddr32(x, y) = d;
        }
    }
}

static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
                             const SkString& name,
                             const char* renderModeDescriptor,
                             SkBitmap* diff) {
    SkBitmap copy;
    const SkBitmap* bm = ⌖
    if (target.config() != SkBitmap::kARGB_8888_Config) {
        target.copyTo(&copy, SkBitmap::kARGB_8888_Config);
        bm = ©
    }
    SkBitmap baseCopy;
    const SkBitmap* bp = &base;
    if (base.config() != SkBitmap::kARGB_8888_Config) {
        base.copyTo(&baseCopy, SkBitmap::kARGB_8888_Config);
        bp = &baseCopy;
    }

    force_all_opaque(*bm);
    force_all_opaque(*bp);

    const int w = bm->width();
    const int h = bm->height();
    if (w != bp->width() || h != bp->height()) {
        SkDebugf(
"---- %s dimensions mismatch for %s base [%d %d] current [%d %d]\n",
                 renderModeDescriptor, name.c_str(),
                 bp->width(), bp->height(), w, h);
        return ERROR_DIMENSION_MISMATCH;
    }

    SkAutoLockPixels bmLock(*bm);
    SkAutoLockPixels baseLock(*bp);

    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            SkPMColor c0 = *bp->getAddr32(x, y);
            SkPMColor c1 = *bm->getAddr32(x, y);
            if (c0 != c1) {
                SkDebugf(
"----- %s pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
                         renderModeDescriptor, name.c_str(), x, y, c0, c1);

                if (diff) {
                    diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
                    diff->allocPixels();
                    compute_diff(*bm, *bp, diff);
                }
                return ERROR_PIXEL_MISMATCH;
            }
        }
    }

    // they're equal
    return ERROR_NONE;
}

static bool write_document(const SkString& path,
                           const SkDynamicMemoryWStream& document) {
    SkFILEWStream stream(path.c_str());
    SkAutoDataUnref data(document.copyToData());
    return stream.writeData(data.get());
}

enum Backend {
  kRaster_Backend,
  kGPU_Backend,
  kPDF_Backend,
  kXPS_Backend,
};

enum ConfigFlags {
    kNone_ConfigFlag  = 0x0,
    /* Write GM images if a write path is provided. */
    kWrite_ConfigFlag = 0x1,
    /* Read comparison GM images if a read path is provided. */
    kRead_ConfigFlag  = 0x2,
    kRW_ConfigFlag    = (kWrite_ConfigFlag | kRead_ConfigFlag),
};

struct ConfigData {
    SkBitmap::Config                fConfig;
    Backend                         fBackend;
    GLContextType                   fGLContextType; // GPU backend only
    int                             fSampleCnt;     // GPU backend only
    ConfigFlags                     fFlags;
    const char*                     fName;
};

/// Returns true if processing should continue, false to skip the
/// remainder of this config for this GM.
//@todo thudson 22 April 2011 - could refactor this to take in
// a factory to generate the context, always call readPixels()
// (logically a noop for rasters, if wasted time), and thus collapse the
// GPU special case and also let this be used for SkPicture testing.
static void setup_bitmap(const ConfigData& gRec, SkISize& size,
                         SkBitmap* bitmap) {
    bitmap->setConfig(gRec.fConfig, size.width(), size.height());
    bitmap->allocPixels();
    bitmap->eraseColor(0);
}

#include "SkDrawFilter.h"
class BWTextDrawFilter : public SkDrawFilter {
public:
    virtual void filter(SkPaint*, Type) SK_OVERRIDE;
};
void BWTextDrawFilter::filter(SkPaint* p, Type t) {
    if (kText_Type == t) {
        p->setAntiAlias(false);
    }
}

static void installFilter(SkCanvas* canvas) {
    if (gForceBWtext) {
        canvas->setDrawFilter(new BWTextDrawFilter)->unref();
    }
}

static void invokeGM(GM* gm, SkCanvas* canvas, bool isPDF = false) {
    SkAutoCanvasRestore acr(canvas, true);

    if (!isPDF) {
        canvas->concat(gm->getInitialTransform());
    }
    installFilter(canvas);
    gm->draw(canvas);
    canvas->setDrawFilter(NULL);
}

static ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
                                    GrContext* context,
                                    GrRenderTarget* rt,
                                    SkBitmap* bitmap,
                                    bool deferred) {
    SkISize size (gm->getISize());
    setup_bitmap(gRec, size, bitmap);

    if (gRec.fBackend == kRaster_Backend) {
        SkCanvas* canvas;
        if (deferred) {
            canvas = new SkDeferredCanvas;
            canvas->setDevice(new SkDevice(*bitmap))->unref();
        } else {
            canvas = new SkCanvas(*bitmap);
        }
        SkAutoUnref canvasUnref(canvas);
        invokeGM(gm, canvas);
        canvas->flush();
    }
#if SK_SUPPORT_GPU
    else {  // GPU
        if (NULL == context) {
            return ERROR_NO_GPU_CONTEXT;
        }
        SkCanvas* gc;
        if (deferred) {
            gc = new SkDeferredCanvas;
        } else {
            gc = new SkGpuCanvas(context, rt);
        }
        SkAutoUnref gcUnref(gc);
        gc->setDevice(new SkGpuDevice(context, rt))->unref();
        invokeGM(gm, gc);
        // the device is as large as the current rendertarget, so we explicitly
        // only readback the amount we expect (in size)
        // overwrite our previous allocation
        bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
                                                       size.fHeight);
        gc->readPixels(bitmap, 0, 0);
    }
#endif
    return ERROR_NONE;
}

static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
                                        SkPicture* pict, SkBitmap* bitmap) {
    SkISize size = gm->getISize();
    setup_bitmap(gRec, size, bitmap);
    SkCanvas canvas(*bitmap);
    installFilter(&canvas);
    canvas.drawPicture(*pict);
}

static void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
#ifdef SK_SUPPORT_PDF
    SkMatrix initialTransform = gm->getInitialTransform();
    SkISize pageSize = gm->getISize();
    SkPDFDevice* dev = NULL;
    if (initialTransform.isIdentity()) {
        dev = new SkPDFDevice(pageSize, pageSize, initialTransform);
    } else {
        SkRect content = SkRect::MakeWH(SkIntToScalar(pageSize.width()),
                                        SkIntToScalar(pageSize.height()));
        initialTransform.mapRect(&content);
        content.intersect(0, 0, SkIntToScalar(pageSize.width()),
                                SkIntToScalar(pageSize.height()));
        SkISize contentSize =
            SkISize::Make(SkScalarRoundToInt(content.width()),
                          SkScalarRoundToInt(content.height()));
        dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
    }
    SkAutoUnref aur(dev);

    SkCanvas c(dev);
    invokeGM(gm, &c, true);

    SkPDFDocument doc;
    doc.appendPage(dev);
    doc.emitPDF(&pdf);
#endif
}

static void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
#ifdef SK_SUPPORT_XPS
    SkISize size = gm->getISize();

    SkSize trimSize = SkSize::Make(SkIntToScalar(size.width()),
                                   SkIntToScalar(size.height()));
    static const SkScalar inchesPerMeter = SkScalarDiv(10000, 254);
    static const SkScalar upm = 72 * inchesPerMeter;
    SkVector unitsPerMeter = SkPoint::Make(upm, upm);
    static const SkScalar ppm = 200 * inchesPerMeter;
    SkVector pixelsPerMeter = SkPoint::Make(ppm, ppm);

    SkXPSDevice* dev = new SkXPSDevice();
    SkAutoUnref aur(dev);

    SkCanvas c(dev);
    dev->beginPortfolio(&xps);
    dev->beginSheet(unitsPerMeter, pixelsPerMeter, trimSize);
    invokeGM(gm, &c);
    dev->endSheet();
    dev->endPortfolio();

#endif
}

static ErrorBitfield write_reference_image(const ConfigData& gRec,
                                           const char writePath [],
                                           const char renderModeDescriptor [],
                                           const SkString& name,
                                           SkBitmap& bitmap,
                                           SkDynamicMemoryWStream* document) {
    SkString path;
    bool success = false;
    if (gRec.fBackend == kRaster_Backend ||
        gRec.fBackend == kGPU_Backend ||
        (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF)) {

        path = make_filename(writePath, renderModeDescriptor, name, "png");
        success = write_bitmap(path, bitmap);
    }
    if (kPDF_Backend == gRec.fBackend) {
        path = make_filename(writePath, renderModeDescriptor, name, "pdf");
        success = write_document(path, *document);
    }
    if (kXPS_Backend == gRec.fBackend) {
        path = make_filename(writePath, renderModeDescriptor, name, "xps");
        success = write_document(path, *document);
    }
    if (success) {
        return ERROR_NONE;
    } else {
        fprintf(stderr, "FAILED to write %s\n", path.c_str());
        return ERROR_WRITING_REFERENCE_IMAGE;
    }
}

static ErrorBitfield compare_to_reference_image(const SkString& name,
                                                SkBitmap &bitmap,
                                                const SkBitmap& comparisonBitmap,
                                                const char diffPath [],
                                                const char renderModeDescriptor []) {
    ErrorBitfield errors;
    SkBitmap diffBitmap;
    errors = compare(bitmap, comparisonBitmap, name, renderModeDescriptor,
                     diffPath ? &diffBitmap : NULL);
    if ((ERROR_NONE != errors) && diffPath) {
        // write out the generated image
        SkString genName = make_filename(diffPath, "", name, "png");
        if (!write_bitmap(genName, bitmap)) {
            errors |= ERROR_WRITING_REFERENCE_IMAGE;
        }
    }
    return errors;
}

static ErrorBitfield compare_to_reference_image(const char readPath [],
                                                const SkString& name,
                                                SkBitmap &bitmap,
                                                const char diffPath [],
                                                const char renderModeDescriptor []) {
    SkString path = make_filename(readPath, "", name, "png");
    SkBitmap orig;
    if (SkImageDecoder::DecodeFile(path.c_str(), &orig,
                                   SkBitmap::kARGB_8888_Config,
                                   SkImageDecoder::kDecodePixels_Mode, NULL)) {
        return compare_to_reference_image(name, bitmap,
                                          orig, diffPath,
                                          renderModeDescriptor);
    } else {
        if (gNotifyMissingReadReference) {
            fprintf(stderr, "FAILED to read %s\n", path.c_str());
        }
        return ERROR_READING_REFERENCE_IMAGE;
    }
}

static ErrorBitfield handle_test_results(GM* gm,
                                         const ConfigData& gRec,
                                         const char writePath [],
                                         const char readPath [],
                                         const char diffPath [],
                                         const char renderModeDescriptor [],
                                         SkBitmap& bitmap,
                                         SkDynamicMemoryWStream* pdf,
                                         const SkBitmap* comparisonBitmap) {
    SkString name = make_name(gm->shortName(), gRec.fName);
    ErrorBitfield retval = ERROR_NONE;

    if (readPath && (gRec.fFlags & kRead_ConfigFlag)) {
        retval |= compare_to_reference_image(readPath, name, bitmap,
                                             diffPath, renderModeDescriptor);
    }
    if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
        retval |= write_reference_image(gRec, writePath, renderModeDescriptor,
                                        name, bitmap, pdf);
    }
    if (comparisonBitmap) {
        retval |= compare_to_reference_image(name, bitmap,
                                             *comparisonBitmap, diffPath,
                                             renderModeDescriptor);
    }
    return retval;
}

static SkPicture* generate_new_picture(GM* gm) {
    // Pictures are refcounted so must be on heap
    SkPicture* pict = new SkPicture;
    SkCanvas* cv = pict->beginRecording(1000, 1000);
    invokeGM(gm, cv);
    pict->endRecording();

    return pict;
}

static SkPicture* stream_to_new_picture(const SkPicture& src) {

    // To do in-memory commiunications with a stream, we need to:
    // * create a dynamic memory stream
    // * copy it into a buffer
    // * create a read stream from it
    // ?!?!

    SkDynamicMemoryWStream storage;
    src.serialize(&storage);

    int streamSize = storage.getOffset();
    SkAutoMalloc dstStorage(streamSize);
    void* dst = dstStorage.get();
    //char* dst = new char [streamSize];
    //@todo thudson 22 April 2011 when can we safely delete [] dst?
    storage.copyTo(dst);
    SkMemoryStream pictReadback(dst, streamSize);
    SkPicture* retval = new SkPicture (&pictReadback);
    return retval;
}

// Test: draw into a bitmap or pdf.
// Depending on flags, possibly compare to an expected image
// and possibly output a diff image if it fails to match.
static ErrorBitfield test_drawing(GM* gm,
                                  const ConfigData& gRec,
                                  const char writePath [],
                                  const char readPath [],
                                  const char diffPath [],
                                  GrContext* context,
                                  GrRenderTarget* rt,
                                  SkBitmap* bitmap) {
    SkDynamicMemoryWStream document;

    if (gRec.fBackend == kRaster_Backend ||
        gRec.fBackend == kGPU_Backend) {
        // Early exit if we can't generate the image.
        ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap,
            false);
        if (ERROR_NONE != errors) {
            return errors;
        }
    } else if (gRec.fBackend == kPDF_Backend) {
        generate_pdf(gm, document);
#if CAN_IMAGE_PDF
        SkAutoDataUnref data(document.copyToData());
        SkMemoryStream stream(data->data(), data->size());
        SkPDFDocumentToBitmap(&stream, bitmap);
#endif
    } else if (gRec.fBackend == kXPS_Backend) {
        generate_xps(gm, document);
    }
    return handle_test_results(gm, gRec, writePath, readPath, diffPath,
                               "", *bitmap, &document, NULL);
}

static ErrorBitfield test_deferred_drawing(GM* gm,
                         const ConfigData& gRec,
                         const SkBitmap& comparisonBitmap,
                         const char diffPath [],
                         GrContext* context,
                         GrRenderTarget* rt) {
    SkDynamicMemoryWStream document;

    if (gRec.fBackend == kRaster_Backend ||
        gRec.fBackend == kGPU_Backend) {
        SkBitmap bitmap;
        // Early exit if we can't generate the image, but this is
        // expected in some cases, so don't report a test failure.
        if (!generate_image(gm, gRec, context, rt, &bitmap, true)) {
            return ERROR_NONE;
        }
        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
                                   "-deferred", bitmap, NULL, &comparisonBitmap);
    }
    return ERROR_NONE;
}

static ErrorBitfield test_picture_playback(GM* gm,
                                           const ConfigData& gRec,
                                           const SkBitmap& comparisonBitmap,
                                           const char readPath [],
                                           const char diffPath []) {
    SkPicture* pict = generate_new_picture(gm);
    SkAutoUnref aur(pict);

    if (kRaster_Backend == gRec.fBackend) {
        SkBitmap bitmap;
        generate_image_from_picture(gm, gRec, pict, &bitmap);
        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
                            "-replay", bitmap, NULL, &comparisonBitmap);
    } else {
        return ERROR_NONE;
    }
}

static ErrorBitfield test_picture_serialization(GM* gm,
                                                const ConfigData& gRec,
                                                const SkBitmap& comparisonBitmap,
                                                const char readPath [],
                                                const char diffPath []) {
    SkPicture* pict = generate_new_picture(gm);
    SkAutoUnref aurp(pict);
    SkPicture* repict = stream_to_new_picture(*pict);
    SkAutoUnref aurr(repict);

    if (kRaster_Backend == gRec.fBackend) {
        SkBitmap bitmap;
        generate_image_from_picture(gm, gRec, repict, &bitmap);
        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
                            "-serialize", bitmap, NULL, &comparisonBitmap);
    } else {
        return ERROR_NONE;
    }
}

struct PipeFlagComboData {
    const char* name;
    uint32_t flags;
};

static PipeFlagComboData gPipeWritingFlagCombos[] = {
    { "", 0 },
    { " cross-process", SkGPipeWriter::kCrossProcess_Flag },
    { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag
        | SkGPipeWriter::kSharedAddressSpace_Flag }
};

static ErrorBitfield test_pipe_playback(GM* gm,
                                        const ConfigData& gRec,
                                        const SkBitmap& comparisonBitmap,
                                        const char readPath [],
                                        const char diffPath []) {
    if (kRaster_Backend != gRec.fBackend) {
        return ERROR_NONE;
    }
    ErrorBitfield errors = ERROR_NONE;
    for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
        SkBitmap bitmap;
        SkISize size = gm->getISize();
        setup_bitmap(gRec, size, &bitmap);
        SkCanvas canvas(bitmap);
        PipeController pipeController(&canvas);
        SkGPipeWriter writer;
        SkCanvas* pipeCanvas = writer.startRecording(&pipeController,
                                                     gPipeWritingFlagCombos[i].flags);
        invokeGM(gm, pipeCanvas);
        writer.endRecording();
        SkString string("-pipe");
        string.append(gPipeWritingFlagCombos[i].name);
        errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
                                   string.c_str(), bitmap, NULL, &comparisonBitmap);
        if (errors != ERROR_NONE) {
            break;
        }
    }
    return errors;
}

static ErrorBitfield test_tiled_pipe_playback(GM* gm,
                                        const ConfigData& gRec,
                                        const SkBitmap& comparisonBitmap,
                                        const char readPath [],
                                        const char diffPath []) {
    if (kRaster_Backend != gRec.fBackend) {
        return ERROR_NONE;
    }
    ErrorBitfield errors = ERROR_NONE;
    for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
        SkBitmap bitmap;
        SkISize size = gm->getISize();
        setup_bitmap(gRec, size, &bitmap);
        SkCanvas canvas(bitmap);
        TiledPipeController pipeController(bitmap);
        SkGPipeWriter writer;
        SkCanvas* pipeCanvas = writer.startRecording(&pipeController,
                                                     gPipeWritingFlagCombos[i].flags);
        invokeGM(gm, pipeCanvas);
        writer.endRecording();
        SkString string("-tiled pipe");
        string.append(gPipeWritingFlagCombos[i].name);
        errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
                                      string.c_str(), bitmap, NULL, &comparisonBitmap);
        if (errors != ERROR_NONE) {
            break;
        }
    }
    return errors;
}

static void write_picture_serialization(GM* gm, const ConfigData& rec,
                                        const char writePicturePath[]) {
    // only do this once, so we pick raster
    if (kRaster_Backend == rec.fBackend &&
        SkBitmap::kARGB_8888_Config == rec.fConfig) {

        SkAutoTUnref<SkPicture> pict(generate_new_picture(gm));

        const char* pictureSuffix = "skp";
        SkString path = make_filename(writePicturePath, "",
                                      SkString(gm->shortName()), pictureSuffix);

        SkFILEWStream stream(path.c_str());
        pict->serialize(&stream);
    }
}

#if SK_SUPPORT_GPU
static const GLContextType kDontCare_GLContextType = GrContextFactory::kNative_GLContextType;
#else
static const GLContextType kDontCare_GLContextType = 0;
#endif

// If the platform does not support writing PNGs of PDFs then there will be no
// comparison images to read. However, we can always write the .pdf files
static const ConfigFlags kPDFConfigFlags = CAN_IMAGE_PDF ? kRW_ConfigFlag :
                                                           kWrite_ConfigFlag;

static const ConfigData gRec[] = {
    { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "8888" },
    { SkBitmap::kARGB_4444_Config, kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "4444" },
    { SkBitmap::kRGB_565_Config,   kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "565" },
#if defined(SK_SCALAR_IS_FLOAT) && SK_SUPPORT_GPU
    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kNative_GLContextType,  0, kRW_ConfigFlag,    "gpu" },
#ifndef SK_BUILD_FOR_ANDROID
    // currently we don't want to run MSAA tests on Android
    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kNative_GLContextType, 16, kRW_ConfigFlag,    "msaa16" },
#endif
    /* The debug context does not generate images */
    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kDebug_GLContextType,   0, kNone_ConfigFlag,  "debug" },
#if SK_ANGLE
    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kANGLE_GLContextType,   0, kRW_ConfigFlag,    "angle" },
    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kANGLE_GLContextType,  16, kRW_ConfigFlag,    "anglemsaa16" },
#endif // SK_ANGLE
#ifdef SK_MESA
    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kMESA_GLContextType,    0, kRW_ConfigFlag,    "mesa" },
#endif // SK_MESA
#endif // defined(SK_SCALAR_IS_FLOAT) && SK_SUPPORT_GPU
#ifdef SK_SUPPORT_XPS
    /* At present we have no way of comparing XPS files (either natively or by converting to PNG). */
    { SkBitmap::kARGB_8888_Config, kXPS_Backend,    kDontCare_GLContextType,                  0, kWrite_ConfigFlag, "xps" },
#endif // SK_SUPPORT_XPS
#ifdef SK_SUPPORT_PDF
    { SkBitmap::kARGB_8888_Config, kPDF_Backend,    kDontCare_GLContextType,                  0, kPDFConfigFlags,   "pdf" },
#endif // SK_SUPPORT_PDF
};

static void usage(const char * argv0) {
    SkDebugf("%s\n", argv0);
    SkDebugf("    [-w writePath] [-r readPath] [-d diffPath] [-i resourcePath]\n");
    SkDebugf("    [-wp writePicturePath]\n");
    SkDebugf("    [--config ");
    for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
        if (i > 0) {
            SkDebugf("|");
        }
        SkDebugf(gRec[i].fName);
    }
    SkDebugf(" ]\n");
    SkDebugf("    [--noreplay] [--nopipe] [--serialize] [--forceBWtext] [--nopdf] \n"
             "    [--tiledPipe] \n"
             "    [--nodeferred] [--match substring] [--notexturecache]\n"
             "    [-h|--help]\n"
             );
    SkDebugf("    writePath: directory to write rendered images in.\n");
    SkDebugf("    writePicturePath: directory to write images to in .skp format.\n");
    SkDebugf(
             "    readPath: directory to read reference images from;\n"
             "        reports if any pixels mismatch between reference and new images\n");
    SkDebugf("    diffPath: directory to write difference images in.\n");
    SkDebugf("    resourcePath: directory that stores image resources.\n");
    SkDebugf("    --noreplay: do not exercise SkPicture replay.\n");
    SkDebugf("    --nopipe: Skip SkGPipe replay.\n");
    SkDebugf("    --tiledPipe: Exercise tiled SkGPipe replay.\n");
    SkDebugf(
             "    --serialize: exercise SkPicture serialization & deserialization.\n");
    SkDebugf("    --forceBWtext: disable text anti-aliasing.\n");
    SkDebugf("    --nopdf: skip the pdf rendering test pass.\n");
    SkDebugf("    --nodeferred: skip the deferred rendering test pass.\n");
    SkDebugf("    --match foo: will only run tests that substring match foo.\n");
    SkDebugf("    --notexturecache: disable the gpu texture cache.\n");
    SkDebugf("    -h|--help : Show this help message. \n");
}

static int findConfig(const char config[]) {
    for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
        if (!strcmp(config, gRec[i].fName)) {
            return i;
        }
    }
    return -1;
}

static bool skip_name(const SkTDArray<const char*> array, const char name[]) {
    if (0 == array.count()) {
        // no names, so don't skip anything
        return false;
    }
    for (int i = 0; i < array.count(); ++i) {
        if (strstr(name, array[i])) {
            // found the name, so don't skip
            return false;
        }
    }
    return true;
}

namespace skiagm {
#if SK_SUPPORT_GPU
SkAutoTUnref<GrContext> gGrContext;
/**
 * Sets the global GrContext, accessible by indivual GMs
 */
static void SetGr(GrContext* grContext) {
    SkSafeRef(grContext);
    gGrContext.reset(grContext);
}

/**
 * Gets the global GrContext, can be called by GM tests.
 */
GrContext* GetGr();
GrContext* GetGr() {
    return gGrContext.get();
}

/**
 * Sets the global GrContext and then resets it to its previous value at
 * destruction.
 */
class AutoResetGr : SkNoncopyable {
public:
    AutoResetGr() : fOld(NULL) {}
    void set(GrContext* context) {
        SkASSERT(NULL == fOld);
        fOld = GetGr();
        SkSafeRef(fOld);
        SetGr(context);
    }
    ~AutoResetGr() { SetGr(fOld); SkSafeUnref(fOld); }
private:
    GrContext* fOld;
};
#else
GrContext* GetGr() { return NULL; }
#endif
}

int main(int argc, char * const argv[]) {

#ifdef SK_ENABLE_INST_COUNT
    gPrintInstCount = true;
#endif

    SkGraphics::Init();
    // we don't need to see this during a run
    gSkSuppressFontCachePurgeSpew = true;

    setSystemPreferences();

    const char* writePath = NULL;   // if non-null, where we write the originals
    const char* writePicturePath = NULL;    // if non-null, where we write serialized pictures
    const char* readPath = NULL;    // if non-null, were we read from to compare
    const char* diffPath = NULL;    // if non-null, where we write our diffs (from compare)
    const char* resourcePath = NULL;// if non-null, where we read from for image resources

    SkTDArray<const char*> fMatches;

    bool doPDF = true;
    bool doReplay = true;
    bool doPipe = true;
    bool doTiledPipe = false;
    bool doSerialize = false;
    bool doDeferred = true;
    bool disableTextureCache = false;
    SkTDArray<size_t> configs;
    bool userConfig = false;

    gNotifyMissingReadReference = true;

    const char* const commandName = argv[0];
    char* const* stop = argv + argc;
    for (++argv; argv < stop; ++argv) {
        if (strcmp(*argv, "-w") == 0) {
            argv++;
            if (argv < stop && **argv) {
                writePath = *argv;
            }
        } else if (strcmp(*argv, "-wp") == 0) {
            argv++;
            if (argv < stop && **argv) {
                writePicturePath = *argv;
            }
        } else if (strcmp(*argv, "-r") == 0) {
            argv++;
            if (argv < stop && **argv) {
                readPath = *argv;
            }
        } else if (strcmp(*argv, "-d") == 0) {
            argv++;
            if (argv < stop && **argv) {
                diffPath = *argv;
            }
        } else if (strcmp(*argv, "-i") == 0) {
            argv++;
            if (argv < stop && **argv) {
                resourcePath = *argv;
            }
        } else if (strcmp(*argv, "--forceBWtext") == 0) {
            gForceBWtext = true;
        } else if (strcmp(*argv, "--nopipe") == 0) {
            doPipe = false;
        } else if (strcmp(*argv, "--tiledPipe") == 0) {
            doTiledPipe = true;
        } else if (strcmp(*argv, "--noreplay") == 0) {
            doReplay = false;
        } else if (strcmp(*argv, "--nopdf") == 0) {
            doPDF = false;
        } else if (strcmp(*argv, "--nodeferred") == 0) {
            doDeferred = false;
        } else if (strcmp(*argv, "--disable-missing-warning") == 0) {
            gNotifyMissingReadReference = false;
        } else if (strcmp(*argv, "--enable-missing-warning") == 0) {
            gNotifyMissingReadReference = true;
        } else if (strcmp(*argv, "--serialize") == 0) {
            doSerialize = true;
        } else if (strcmp(*argv, "--match") == 0) {
            ++argv;
            if (argv < stop && **argv) {
                // just record the ptr, no need for a deep copy
                *fMatches.append() = *argv;
            }
        } else if (strcmp(*argv, "--notexturecache") == 0) {
            disableTextureCache = true;
        } else if (strcmp(*argv, "--config") == 0) {
            argv++;
            if (argv < stop) {
                int index = findConfig(*argv);
                if (index >= 0) {
                    *configs.append() = index;
                    userConfig = true;
                } else {
                    SkString str;
                    str.printf("unrecognized config %s\n", *argv);
                    SkDebugf(str.c_str());
                    usage(commandName);
                    return -1;
                }
            } else {
                SkDebugf("missing arg for --config\n");
                usage(commandName);
                return -1;
            }
        } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) {
            usage(commandName);
            return -1;
        } else {
            usage(commandName);
            return -1;
        }
    }
    if (argv != stop) {
        usage(commandName);
        return -1;
    }

    if (!userConfig) {
        // if no config is specified by user, we add them all.
        for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
            *configs.append() = i;
        }
    }

    GM::SetResourcePath(resourcePath);

    if (readPath) {
        fprintf(stderr, "reading from %s\n", readPath);
    }
    if (writePath) {
        fprintf(stderr, "writing to %s\n", writePath);
    }
    if (writePicturePath) {
        fprintf(stderr, "writing pictures to %s\n", writePicturePath);
    }
    if (resourcePath) {
        fprintf(stderr, "reading resources from %s\n", resourcePath);
    }

    // Accumulate success of all tests.
    int testsRun = 0;
    int testsPassed = 0;
    int testsFailed = 0;
    int testsMissingReferenceImages = 0;

#if SK_SUPPORT_GPU
    GrContextFactory* grFactory = new GrContextFactory;
    if (disableTextureCache) {
        skiagm::GetGr()->setTextureCacheLimits(0, 0);
    }
#endif

    SkTArray<SkString> failedTests;

    Iter iter;
    GM* gm;
    while ((gm = iter.next()) != NULL) {
        const char* shortName = gm->shortName();
        if (skip_name(fMatches, shortName)) {
            SkDELETE(gm);
            continue;
        }

        SkISize size = gm->getISize();
        SkDebugf("drawing... %s [%d %d]\n", shortName,
                 size.width(), size.height());
        SkBitmap forwardRenderedBitmap;

        for (int i = 0; i < configs.count(); i++) {
            ConfigData config = gRec[configs[i]];
            // Skip any tests that we don't even need to try.
            uint32_t gmFlags = gm->getFlags();
            if ((kPDF_Backend == config.fBackend) &&
                (!doPDF || (gmFlags & GM::kSkipPDF_Flag)))
            {
                continue;
            }

            // Now we know that we want to run this test and record its
            // success or failure.
            ErrorBitfield testErrors = ERROR_NONE;
            GrRenderTarget* renderTarget = NULL;
#if SK_SUPPORT_GPU
            SkAutoTUnref<GrRenderTarget> rt;
            AutoResetGr autogr;
            if ((ERROR_NONE == testErrors) &&
                kGPU_Backend == config.fBackend) {
                GrContext* gr = grFactory->get(config.fGLContextType);
                bool grSuccess = false;
                if (gr) {
                    // create a render target to back the device
                    GrTextureDesc desc;
                    desc.fConfig = kSkia8888_PM_GrPixelConfig;
                    desc.fFlags = kRenderTarget_GrTextureFlagBit;
                    desc.fWidth = gm->getISize().width();
                    desc.fHeight = gm->getISize().height();
                    desc.fSampleCnt = config.fSampleCnt;
                    GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0);
                    if (tex) {
                        rt.reset(tex->asRenderTarget());
                        rt.get()->ref();
                        tex->unref();
                        autogr.set(gr);
                        renderTarget = rt.get();
                        grSuccess = NULL != renderTarget;
                    }
                }
                if (!grSuccess) {
                    testErrors |= ERROR_NO_GPU_CONTEXT;
                }
            }
#endif

            if (ERROR_NONE == testErrors) {
                testErrors |= test_drawing(gm, config,
                                           writePath, readPath, diffPath,
                                           GetGr(),
                                           renderTarget, &forwardRenderedBitmap);
            }

            if (doDeferred && !testErrors &&
                (kGPU_Backend == config.fBackend ||
                 kRaster_Backend == config.fBackend)) {
                testErrors |= test_deferred_drawing(gm, config,
                                                    forwardRenderedBitmap,
                                                    diffPath, GetGr(), renderTarget);
            }

            if ((ERROR_NONE == testErrors) && doReplay &&
                !(gmFlags & GM::kSkipPicture_Flag)) {
                testErrors |= test_picture_playback(gm, config,
                                                    forwardRenderedBitmap,
                                                    readPath, diffPath);
            }

            if ((ERROR_NONE == testErrors) && doPipe &&
                !(gmFlags & GM::kSkipPipe_Flag)) {
                testErrors |= test_pipe_playback(gm, config,
                                                 forwardRenderedBitmap,
                                                 readPath, diffPath);
            }

            if ((ERROR_NONE == testErrors) && doTiledPipe &&
                !SkToBool(gmFlags & (GM::kSkipPipe_Flag | GM::kSkipTiled_Flag))) {
                testErrors |= test_tiled_pipe_playback(gm, config,
                                                 forwardRenderedBitmap,
                                                 readPath, diffPath);
            }

            if ((ERROR_NONE == testErrors) && doSerialize  &&
                !(gmFlags & GM::kSkipPicture_Flag)) {
                testErrors |= test_picture_serialization(gm, config,
                                                         forwardRenderedBitmap,
                                                         readPath, diffPath);
            }

            if (!(gmFlags & GM::kSkipPicture_Flag) && writePicturePath) {
                write_picture_serialization(gm, config, writePicturePath);
            }

            // Update overall results.
            // We only tabulate the particular error types that we currently
            // care about (e.g., missing reference images). Later on, if we
            // want to also tabulate pixel mismatches vs dimension mistmatches
            // (or whatever else), we can do so.
            testsRun++;
            if (ERROR_NONE == testErrors) {
                testsPassed++;
            } else if (ERROR_READING_REFERENCE_IMAGE & testErrors) {
                testsMissingReferenceImages++;
            } else {
                testsFailed++;

                failedTests.push_back(make_name(shortName, config.fName));
            }
        }
        SkDELETE(gm);
    }
    SkDebugf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
             testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
    for (int i = 0; i < failedTests.count(); ++i) {
        SkDebugf("\t\t%s\n", failedTests[i].c_str());
    }

#if SK_SUPPORT_GPU

#if GR_CACHE_STATS
    for (int i = 0; i < configs.count(); i++) {
        ConfigData config = gRec[configs[i]];

        if (kGPU_Backend == config.fBackend) {
            GrContext* gr = grFactory->get(config.fGLContextType);

            SkDebugf("config: %s %x\n", config.fName, gr);
            gr->printCacheStats();
        }
    }
#endif

    delete grFactory;
#endif
    SkGraphics::Term();

    return (0 == testsFailed) ? 0 : -1;
}


text:
@inproceedings{10.1145/2537734.2537735,
author = {Azzopardi, Leif},
title = {Economic Models of Search},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537735},
doi = {10.1145/2537734.2537735},
abstract = {Searching is inherently an interactive process usually requiring a number of queries to be submitted and a number of documents to be assessed in order to find the desired amount of relevant information. While numerous models of search have been proposed, they have been largely conceptual in nature providing a descriptive account of the search process. For example, Bates' Berry Picking metaphor aptly describes how information seekers forage for relevant information [4]. However it lacks any predictive or explanatory power. In this talk, I will outline how microeconomic theory can be applied to interactive information retrieval, where the search process can be viewed as a combination of inputs (i.e. queries and assessments) which are used to "produce" output (i.e. relevance). Under this view, it is possible to build models that not only describe the relationship between interaction, cost and gain, but also explain and predict behaviour. During the talk, I will run through a number of examples of how economics can explain different behaviours. For example, why PhD students should search more than their supervisors (using an economic model developed by Cooper [6]), why queries are short [1], why Boolean searchers need to explore more results, and why it is okay to look at the first few results when searching the web [2]. I shall then describe how the cost of different interactions affect search behaviour [3], before extending the current theory to include other variables (such as the time spent on the search result page, the interaction with snippets, etc) to create more sophisticated and realistic models. Essentially, I will argue that by using such models we can:1. theorise and predict how users will behave when interacting with systems,2. ascertain how the costs of different interaction will influence search behaviour,3. understand why particular interaction styles, strategies, techniques are or are not adopted by users, and,4. determine what interactions and functionalities are worthwhile based on their expected gain and associated costs.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {1},
numpages = {1},
keywords = {retrieval strategies, information behaviours},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537747,
author = {Al Maqbali, Hilal and Scholer, Falk and Thom, James A. and Wu, Mingfang},
title = {Using Eye Tracking for Evaluating Web Search Interfaces},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537747},
doi = {10.1145/2537734.2537747},
abstract = {Using eye tracking in the evaluation of web search interfaces can provide rich information on users' information search behaviour, particularly in the matter of user interaction with different informative components on a search results screen. One of the main issues affecting the use of eye tracking in research is the quality of captured eye movements (calibration), therefore, in this paper, we propose a method that allows us to determine the quality of calibration, since the existing eye tracking system (Tobii Studio) does not provide any criteria for this aspect. Another issue addressed in this paper is the adaptation of gaze direction. We use a black screen displaying for 3 seconds between screens to avoid the effect of the previous screen on user gaze direction on the coming screen. A further issue when employing eye tracking in the evaluation of web search interfaces is the selection of the appropriate filter for the raw gaze-points data. In our studies, we filtered this data by removing noise, identifying gaze points that occur in Area of Interests (AOIs), optimising gaze data and identifying viewed AOIs.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {2–9},
numpages = {8},
keywords = {eye tracking, web documents, user studies involving documents, information retrieval},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537742,
author = {Chappell, Timothy and Geva, Shlomo and Nguyen, Anthony and Zuccon, Guido},
title = {Efficient Top-k Retrieval with Signatures},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537742},
doi = {10.1145/2537734.2537742},
abstract = {This paper describes a new method of indexing and searching large binary signature collections to efficiently find similar signatures, addressing the scalability problem in signature search. Signatures offer efficient computation with acceptable measure of similarity in numerous applications. However, performing a complete search with a given search argument (a signature) requires a Hamming distance calculation against every signature in the collection. This quickly becomes excessive when dealing with large collections, presenting issues of scalability that limit their applicability.Our method efficiently finds similar signatures in very large collections, trading memory use and precision for greatly improved search speed. Experimental results demonstrate that our approach is capable of finding a set of nearest signatures to a given search argument with a high degree of speed and fidelity.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {10–17},
numpages = {8},
keywords = {near-duplicate detection, nearest neighbour, document signatures, hamming distance, locality-sensitive hashing, top-k},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537743,
author = {Hawking, David and Griffiths, Kathy},
title = {An Enterprise Search Paradigm Based on Extended Query Auto-Completion: Do We Still Need Search and Navigation?},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537743},
doi = {10.1145/2537734.2537743},
abstract = {Enterprise query auto-completion (QAC) can allow website or intranet visitors to satisfy a need more efficiently than traditional searching and browsing. The limited scope of an enterprise makes it possible to satisfy a high proportion of information needs through completion. Further, the availability of structured sources of completions such as product catalogues compensates for sparsity of log data. Extended forms (X-QAC) can give access to information that is inaccessible via a conventional crawled index.We show that it can be guaranteed that for every suggestion there is a prefix which causes it to appear in the top k suggestions. Using university query logs and structured lists, we quantify the significant keystroke savings attributable to this guarantee (worst case). Such savings may be of particular value for mobile devices. A user experiment showed that a staff lookup task took an average of 61% longer with a conventional search interface than with an X-QAC system.Using wine catalogue data we demonstrate a further extension which allows a user to home in on desired items in faceted-navigation style. We also note that advertisements can be triggered from QAC.Given the advantages and power of X-QAC systems, we envisage that websites and intranets of the [near] future will provide less navigation and rely less on conventional search.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {18–25},
numpages = {8},
keywords = {query sugggestion, query auto-completion, search paradigms},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537737,
author = {Karimi, Sarvnaz and Yin, Jie and Paris, Cecile},
title = {Classifying Microblogs for Disasters},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537737},
doi = {10.1145/2537734.2537737},
abstract = {Monitoring social media in critical disaster situations can potentially assist emergency and media personnel to deal with events as they unfold, and focus their resources where they are most needed. We address the issue of filtering massive amounts of Twitter data to identify high-value messages related to disasters, and to further classify disaster-related messages into those pertaining to particular disaster types, such as earthquake, flooding, fire, or storm. Unlike post-hoc analysis that most previous studies have done, we focus on building a classification model on past incidents to detect tweets about current incidents. Our experimental results demonstrate the feasibility of using classification methods to identify disaster-related tweets. We analyse the effect of different features in classifying tweets and show that using generic features rather than incident-specific ones leads to better generalisation on the effectiveness of classifying unseen incidents.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {26–33},
numpages = {8},
keywords = {disaster management, tweet classification, social media mining},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537741,
author = {Koopman, Bevan and Zuccon, Guido and De Vine, Lance and Bakharia, Aneesha and Bruza, Peter and Sitbon, Laurianne and Gibson, Andrew},
title = {ADCS Reaches Adulthood: An Analysis of the Conference and Its Community over the Last Eighteen Years},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537741},
doi = {10.1145/2537734.2537741},
abstract = {How influential is the Australian Document Computing Symposium (ADCS)? What do ADCS articles speak about and who cites them? Who is the ADCS community and how has it evolved?This paper considers eighteen years of ADCS, investigating both the conference and its community. A content analysis of the proceedings uncovers the diversity of topics covered in ADCS and how these have changed over the years. Citation analysis reveals the impact of the papers. The number of authors and where they originate from reveal who has contributed to the conference. Finally, we generate co-author networks which reveal the collaborations within the community. These networks show how clusters of researchers form, the effect geographic location has on collaboration, and how these have evolved over time.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {34–41},
numpages = {8},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537750,
author = {Li, PengFei (Vincent) and Thomas, Paul and Hawking, David},
title = {Merging Algorithms for Enterprise Search},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537750},
doi = {10.1145/2537734.2537750},
abstract = {Effective enterprise search must draw on a number of sources---for example web pages, telephone directories, and databases. Doing this means we need a way to make a single sorted list from results of very different types.Many merging algorithms have been proposed but none have been applied to this, realistic, application. We report the results of an experiment which simulates heterogeneous enterprise retrieval, in a university setting, and uses multi-grade expert judgements to compare merging algorithms. Merging algorithms considered include several variants of round-robin, several methods proposed by Rasolofo et al. in the Current News Metasearcher, and four novel variations including a learned multi-weight method.We find that the round-robin methods and one of the Rasolofo methods perform significantly worse than others. The GDS_TS method of Rasolofo achieves the highest average NDCG@10 score but the differences between it and the other GDS_methods, local reranking, and the multi-weight method were not significant.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {42–49},
numpages = {8},
keywords = {information retrieval, federated search, results merging},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537749,
author = {Park, Laurence A. F. and Simoff, Simeon},
title = {Power Walk: Revisiting the Random Surfer},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537749},
doi = {10.1145/2537734.2537749},
abstract = {Measurement of graph centrality provides us with an indication of the importance or popularity of each vertex in a graph. When dealing with graphs that are not centrally controlled (such as the Web, social networks and academic citation graphs), centrality measure must 1) correlate with vertex importance/popularity, 2) scale well in terms of computation, and 3) be difficult to manipulate by individuals. The Random Surfer probability transition model, combined with Eigenvalue Centrality produced PageRank, which has shown to satisfy the required properties. Existing centrality measures (including PageRank) make the assumption that all directed edges are positive, implying an endorsement. Recent work on sentiment analysis has shown that this assumption is not valid. In this article, we introduce a new method of transitioning a graph, called Power Walk, that can successfully compute centrality scores for graphs with real weighted edges. We show that it satisfies the desired properties, and that its computation time and centrality ranking is similar to when using the Random Surfer model for non-negative matrices. Finally, stability and convergence analysis shows us that both stability and convergence when using the power method, are dependent on the Power Walk parameter β.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {50–57},
numpages = {8},
keywords = {PageRank, sentiment, graph centrality, random surfer},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537744,
author = {Petri, Matthias and Culpepper, J. Shane and Moffat, Alistair},
title = {Exploring the Magic of WAND},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537744},
doi = {10.1145/2537734.2537744},
abstract = {Web search services process thousands of queries per second, and filter their answers from collections containing very large amounts of data. Fast response to queries is a critical service expectation. The well-known WAND processing strategy is one way of reducing the amount of computation necessary when executing such a query. The value of WAND has now been validated in a wide range of studies, and has become one of the key baselines against which all new top-k processing algorithms are benchmarked. However, most previous implementations of WAND-based retrieval approaches have been in the context of the BM25 Okapi similarity scoring regime. Here we measure the performance of WAND in the context of the alternative Language Model similarity score computation, and find that the dramatic efficiency gains reported in previous studies are no longer achievable. That is, when the primary goal of a retrieval system is to maximize effectiveness, WAND is relatively unhelpful in terms of attaining the secondary objective of maximizing query throughput rates. However, the BM-WAND algorithm does in fact help reducing the percentage of postings to be scored, but with additional computational overhead. We explore a variety of tradeoffs between scoring metric and processing regime and present new insight into how score-safe algorithms interact with rank scoring.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {58–65},
numpages = {8},
keywords = {text indexing, information retrieval, performance},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537751,
author = {Puurula, Antti and Myaeng, Sung-Hyon},
title = {Integrated Instance- and Class-Based Generative Modeling for Text Classification},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537751},
doi = {10.1145/2537734.2537751},
abstract = {Statistical methods for text classification are predominantly based on the paradigm of class-based learning that associates class variables with features, discarding the instances of data after model training. This results in efficient models, but neglects the fine-grained information present in individual documents. Instance-based learning uses this information, but suffers from data sparsity with text data. In this paper, we propose a generative model called Tied Document Mixture (TDM) for extending Multinomial Naive Bayes (MNB) with mixtures of hierarchically smoothed models for documents. Alternatively, TDM can be viewed as a Kernel Density Classifier using class-smoothed Multinomial kernels. TDM is evaluated for classification accuracy on 14 different datasets for multi-label, multi-class and binary-class text classification tasks and compared to instance- and class-based learning baselines. The comparisons to MNB demonstrate a substantial improvement in accuracy as a function of available training documents per class, ranging up to average error reductions of over 26% in sentiment classification and 65% in spam classification. On average TDM is as accurate as the best discriminative classifiers, but retains the linear time complexities of instance-based learning methods, with exact algorithms for both model estimation and inference.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {66–73},
numpages = {8},
keywords = {text classification, generative modeling, instance-based learning, Multinomial Naive Bayes, sparse posterior inference, tied document mixture},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537745,
author = {Scholer, Falk and Moffat, Alistair and Thomas, Paul},
title = {Choices in Batch Information Retrieval Evaluation},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537745},
doi = {10.1145/2537734.2537745},
abstract = {Web search tools are used on a daily basis by billions of people. The commercial providers of these services spend large amounts of money measuring their own effectiveness and benchmarking against their competitors; nothing less than their corporate survival is at stake. Techniques for offline or "batch" evaluation of search quality have received considerable attention, spanning ways of constructing relevance judgments; ways of using them to generate numeric scores; and ways of inferring system "superiority" from sets of such scores.Our purpose in this paper is consider these mechanisms as a chain of inter-dependent activities, in order to explore some of the ramifications of alternative components. By disaggregating the different activities, and asking what the ultimate objective of the measurement process is, we provide new insights into evaluation approaches, and are able to suggest new combinations that might prove fruitful avenues for exploration. Our observations are examined with reference to data collected from a user study covering 34 users undertaking a total of six search tasks each, using two systems of markedly different quality.We hope to encourage broader awareness of the many factors that go into an evaluation of search effectiveness, and of the implications of these choices, and encourage researchers to carefully report all aspects of the evaluation process when describing their system performance experiments.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {74–81},
numpages = {8},
keywords = {information retrieval, evaluation, effectiveness, relevance judgment},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537736,
author = {Sonoda, Takumi and Miura, Takao},
title = {Conditional Collocation in Japanese},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537736},
doi = {10.1145/2537734.2537736},
abstract = {Analysis of Collocation is targeted for Natural Language Processing (NLP). From a linguistic perspective, collocation provides us with a way to place words close together in a natural manner. By this approach, we can examine deep structure of semantics through words and their situation. Although there have been some investigation based on co-occurrence, few discussion has been made about conditional collocation. In this investigation, we discuss a computational approach to extract conditional collocation by using data mining and statistical techniques.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {82–88},
numpages = {7},
keywords = {text mining, conditional collocation, collocation},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537739,
author = {Suominen, Hanna and Hanlen, Leif},
title = {Visual Summarisation of Text for Surveillance and Situational Awareness in Hospitals},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537739},
doi = {10.1145/2537734.2537739},
abstract = {Nosocomial infections (NIs, any infection that a patient contracts in a healthcare institution) cost 100, 000 lives and five billion dollars per year for 300 million Americans alone. Surveillance in hospitals holds the potential of reducing NI rates by more than thirty per cent but performing this task by hand is impossible at scale of every appointment, examination, intervention, and other event in healthcare. Narratives in patient records can indicate NIs and their automated processing could scale out surveillance. This paper describes a text summarisation system for NI surveillance and situational awareness in hospitals. The system is a cascaded sentence, report, and patient classifier. It generates three types of visual summaries for an input of patient narratives and ward maps: cross-sectional statuses at the same point of time, longitudinal trends in time, and highlighted text to see the textual evidence leading to a given status or trend. This gives evidence for and against a given NI in the levels of hospitals, wards, patients, reports, and sentences. The system has excellent recall and precision (e.g., 0.95 and 0.71 for reports) in summarisation for the subset of NIs from fungal species on 1,880 authentic records of 527 patients from 3 hospitals. To demonstrate the system design, we have developed a mobile iPad compatible web-application and a simulation with eighteen patients on three medical wards in one hospital during one month with 61 records in total. The design is extendable to other summarisation tasks.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {89–96},
numpages = {8},
keywords = {nosocomial infections, information storage and retrieval, medical records, medical informatics},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537752,
author = {Albaham, Ameer Tawfik and Salim, Naomie},
title = {Quality Biased Thread Retrieval Using the Voting Model},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537752},
doi = {10.1145/2537734.2537752},
abstract = {Thread retrieval is an essential tool in knowledge-based forums. However, forum content quality varies from excellent to mediocre and spam; thus, search methods should find not only relevant threads but also those with high quality content. Some studies have shown that leveraging quality indicators improves thread search. However, these studies ignored the hierarchical and the conversational structures of threads in estimating topical relevance and content quality. In that regard, this paper introduces leveraging message quality indicators in ranking threads. To achieve this, we first use the Voting Model to convert message level quality features into thread level features. We then train a learning to rank method to combine these thread level features. Preliminary results with some features reveal that representing threads as collections of messages is superior to treating them as concatenations of their messages. The results show also the utility of leveraging message content quality as compared to non quality-based methods.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {97–100},
numpages = {4},
keywords = {information retrieval, information quality, the voting model, forum thread search},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537746,
author = {Crane, Matt and Trotman, Andrew and O'Keefe, Richard},
title = {Malformed UTF-8 and Spam},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537746},
doi = {10.1145/2537734.2537746},
abstract = {In this paper we discuss some of the document encoding errors that were found when scaling our indexer and search engine up to large collections crawled from the web, such as ClueWeb09. In this paper we describe the encoding errors, what effect they could have on indexing and searching, how they are processed within our indexer and search engine and how they relate to the quality of the page measured by another method.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {101–104},
numpages = {4},
keywords = {web documents, information retrieval, procrastination, errors},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537740,
author = {Kreiner, Karl and Immonen, Aapo and Suominen, Hanna},
title = {Crisis Management Knowledge from Social Media},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537740},
doi = {10.1145/2537734.2537740},
abstract = {More and more crisis managers, crisis communicators and laypeople use Twitter and other social media to provide or seek crisis information. In this paper, we focus on retrospective conversion of human-safety related data to crisis management knowledge. First, we study how Twitter data can be classified into the seven categories of the United Nations Development Program Security Model (i.e., Food, Health, Politics, Economic, Personal, Community, and Environment). We conclude that these topic categories are applicable, and supplementing them with classification of individual authors into more generic sources of data (i.e., Official authorities, Media, and Laypeople) allows curating data and assessing crisis maturity. Second, we introduce automated classifiers, based on supervised learning and decision rules, for both tasks and evaluate their correctness. This evaluation uses two datasets collected during the crises of Queensland floods and NZ Earthquake in 2011. The topic classifier performs well in the major categories (i.e., 120--190 training instances) of Economic (F = 0.76) and Community (F = 0.67) while in the minor categories (i.e., 0--60 training instances) the results are more modest (F ≤ 0.41). The source classifier shows excellent results (F ≥ 0.83) in all categories.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {105–108},
numpages = {4},
keywords = {information retrieval, knowledge management, data processing, social network services},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537748,
author = {Moll\'{a}, Diego and Martinez, David and Amini, Iman},
title = {Towards Information Retrieval Evaluation with Reduced and Only Positive Judgements},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537748},
doi = {10.1145/2537734.2537748},
abstract = {This paper proposes a document distance-based approach to automatically expand the number of available relevance judgements when those are limited and reduced to only positive judgements. This may happen, for example, when the only available judgements are extracted from a list of references in a published clinical systematic review. We show that evaluations based on these expanded relevance judgements are more reliable than those using only the initially available judgements. We also show the impact of such an evaluation approach as the number of initial judgements decreases.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {109–112},
numpages = {4},
keywords = {evaluation, relevance judgements expansion, information retrieval},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

@inproceedings{10.1145/2537734.2537738,
author = {Trotman, Andrew and Jia, Xiang-Fei and Crane, Matt},
title = {Managing Short Postings Lists},
year = {2013},
isbn = {9781450325240},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/2537734.2537738},
doi = {10.1145/2537734.2537738},
abstract = {Previous work has examined space saving and throughput increasing techniques for long postings lists in an inverted file search engine. In this contribution we show that highly sporadic terms (terms that occur in 1 or 2 documents) are a high proportion of the unique terms in the collection and that these terms are seen in queries. The previously known space saving method of storing their short postings lists in the vocabulary is compared to storing in the postings file. We quantify the saving as about 6.5%, with no loss in precision, and suggest the adoption of this technique.},
booktitle = {Proceedings of the 18th Australasian Document Computing Symposium},
pages = {113–116},
numpages = {4},
keywords = {storage, procrastination, indexing, efficiency},
location = {Brisbane, Queensland, Australia},
series = {ADCS '13}
}

license: Unlicense

repository: goyalkaraniit/acm-cr

license_type: permissive

repo_name: goyalkaraniit/acm-cr

branch_name: refs/heads/main

extension: bib


text:
package main
import (
	"time"
	"github.com/bagaking/chronos/chronos"
)

func main() {
	chronos.Start();

	for {
		time.Sleep(time.Minute)
	}
}

license: MIT

repository: bagaking/chronos

repo_name: bagaking/chronos

branch_name: refs/heads/master

gha_license_id: MIT

gha_language: Go

extension: go


text:
@article{linquist2015me,
 abstract = {A promising recent development in molecular biology involves viewing the genome as a mini-ecosystem, where genetic elements are compared to organisms and the surrounding cellular and genomic structures are regarded as the local environment. Here, we critically evaluate the prospects of ecological neutral theory (ENT), a popular model in ecology, as it applies at the genomic level. This assessment requires an overview of the controversy surrounding neutral models in community ecology. In particular, we discuss the limitations of using ENT both as an explanation of community dynamics and as a null hypothesis. We then analyse a case study in which ENT has been applied to genomic data. Our central finding is that genetic elements do not conform to the requirements of ENT once its assumptions and limitations are made explicit. We further compare this genome-level application of ENT to two other, more familiar approaches in genomics that rely on neutral mechanisms: Kimura's molecular neutral theory and Lynch's mutational-hazard model. Interestingly, this comparison reveals that there are two distinct concepts of neutrality associated with these models, which we dub ‘fitness neutrality’ and ‘competitive neutrality’. This distinction helps to clarify the various roles for neutral models in genomics, for example in explaining the evolution of genome size.},
 author = {Linquist, Stefan and Cottenie, Karl and Elliott, Tyler A. and Saylor, Brent and Kremer, Stefan C. and Gregory, T. Ryan},
 copyright = {© 2015 John Wiley & Sons Ltd},
 doi = {10.1111/mec.13219},
 file = {linquist_2015_applying_ecological_models_to_communities_of_genetic_elements_-_the_case_of.pdf:/Users/karlcottenie/Google Drive/zotero-library/2015/linquist_2015_applying_ecological_models_to_communities_of_genetic_elements_-_the_case_of.pdf:application/pdf},
 issn = {1365-294X},
 journal = {Molecular Ecology},
 keywords = {ecological neutral theory, genome ecology, molecular ecology, molecular neutral theory, mutation hazard model, transposon ecology},
 language = {en},
 number = {13},
 pages = {3232--3242},
 shorttitle = {Applying ecological models to communities of genetic elements},
 title = {Applying ecological models to communities of genetic elements: the case of neutral theory},
 url = {https://onlinelibrary.wiley.com/doi/abs/10.1111/mec.13219},
 urldate = {2019-04-09},
 volume = {24},
 year = {2015}
}

repository: karl-cottenie/academic-kickstart

repo_name: karl-cottenie/academic-kickstart


text:
package server

import (
	"fmt"
	"github.com/emicklei/go-restful"
	restfulspec "github.com/emicklei/go-restful-openapi"
	"github.com/klaital/volunteer-savvy-backend/internal/pkg/config"
	"github.com/klaital/volunteer-savvy-backend/internal/pkg/filters"
	log "github.com/sirupsen/logrus"
	"net/http"
	"path"
	"time"
)

type Server struct {
	container *restful.Container
	Config    *config.ServiceConfig
}

func New(config *config.ServiceConfig, services []*restful.WebService) (*Server, error) {

	server := &Server{
		container: restful.NewContainer(),
		Config:    config,
	}

	// global filters can go here.  route specific filters go in their route definitions
	// JWT handling is an example of a filter that needs to be route specific, since calls to the Swagger API would fail if it were global
	server.container.Filter(filters.JsonLoggingFilter)

	// set up the APIs we use for this server setup
	server.setupSupportAPI()

	for i := range services {
		server.container.Add(services[i])
	}

	// Expose Swagger-UI
	//http.Handle("/apidocs/", http.StripPrefix("/apidocs/", http.FileServer(http.Dir("~/bin/swagger-ui/dist"))))

	rootService := new(restful.WebService)

	server.addHealthCheck(rootService)
	server.addSwaggerSupport()
	server.container.Add(rootService)

	return server, nil
}

func (server *Server) Serve() {

	var handler http.Handler = server.container

	innerHandler := handler
	handler = http.HandlerFunc(func(respWriter http.ResponseWriter, req *http.Request) {
		innerHandler.ServeHTTP(respWriter, req)
	})

	ipPort := fmt.Sprintf(":%d", server.Config.Port)

	if server.Config.LogLevel == "debug" {
		log.Infof("Server is launching in debug mode")
	}

	log.WithFields(log.Fields{
		"operation": "Serve",
	}).Infof("Server is listening at %s", ipPort)

	httpServer := &http.Server{
		Addr:         ipPort,
		Handler:      handler,
		ReadTimeout:  1 * time.Second,
		WriteTimeout: 1 * time.Second}

	err := httpServer.ListenAndServe()
	if err != nil {
		log.WithFields(log.Fields{
			"operation": "Serve",
		}).Fatalf("server failed: %v", err)
	}
}

func (server *Server) addSwaggerSupport() {
	openAPIService := restfulspec.NewOpenAPIService(restfulspec.Config{
		WebServices: server.container.RegisteredWebServices(),
		APIPath:     server.Config.BasePath + server.Config.APIPath,
	})
	log.Infof("Enabling swagger UI at %s", server.Config.BasePath+server.Config.SwaggerPath)
	http.Handle(
		server.Config.BasePath+server.Config.SwaggerPath,
		http.StripPrefix(
			server.Config.BasePath+server.Config.SwaggerPath,
			http.FileServer(http.Dir("/home/kit/devel/volunteer-savvy-backend/web/swagger-ui/dist"))))

	cors := restful.CrossOriginResourceSharing{
		AllowedHeaders: []string{"Content-Type", "Accept"},
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
		CookiesAllowed: false,
		Container:      server.container,
	}
	server.container.Filter(cors.Filter)
	server.container.Add(openAPIService)
}

func (server *Server) staticFileHandler(req *restful.Request, resp *restful.Response) {
	localFilePath := path.Join(server.Config.StaticContentPath, req.PathParameter("subpath"))
	log.WithField("localPath", localFilePath).Debug("Serving static file")
	http.ServeFile(
		resp.ResponseWriter,
		req.Request,
		localFilePath)
}
func (server *Server) addHealthCheck(service *restful.WebService) {
	service.Route(service.GET(server.Config.HealthCheckPath).To(server.healthCheckHandler))
}

func (server *Server) healthCheckHandler(request *restful.Request, response *restful.Response) {

	// Ensure that the database connection is useable
	if server.Config.GetDbConn() == nil {
		response.WriteHeader(http.StatusInternalServerError)
		log.Error("Database connection not initialized")
		return
	}

	response.WriteHeader(http.StatusOK)
}

// do this for each subpackage/service
func (server *Server) setupSupportAPI() {

	service := new(restful.WebService)
	service.Path(server.Config.BasePath).ApiVersion("0.0.0").Doc("Volunteer-Savvy Backend")

	//
	// Static File Server
	//
	service.Route(
		service.GET("/{subpath:*}").To(server.staticFileHandler))

	server.container.Add(service)
}

repository: Klaital/volunteer-savvy-backend

repo_name: Klaital/volunteer-savvy-backend


text:
require recipes-core/images/core-image-minimal.bb

IMAGE_INSTALL += "libstdc++ adz2 startup mtd-utils"
IMAGE_INSTALL += "openssh openssl openssh-sftp-server"

repository: adps/meta-adlnx

repo_name: adps/meta-adlnx

extension: bb


text:
package executil

import (
	"bytes"
	"fmt"
	"io"
	lg "log"
	"os"
	osexec "os/exec"
)

var (
	out io.Writer // default output stream for ExecPipe
	log *lg.Logger
)

func init() {
	SetOut(os.Stderr)
}

func SetOut(o io.Writer) {
	out = o
	log = lg.New(out, "[executil] ", lg.LstdFlags)
}

type Fds struct{ Out, Err io.Writer }

// ExecPipe is a convenience method to run programs with
// arguments and return their combined stdout/stderr
// output while printing them both to calling process'
// stdout.
func ExecPipe(program string, args ...string) error {
	return ExecPipeToFds(Fds{out, out}, program, args...)
}

// ExecPipeToFds runs the program with specified args and given
// out/err descriptiors. Non-specified (nil) descriptors will be
// replaced with default out stream.
func ExecPipeToFds(fds Fds, program string, args ...string) error {
	log.Printf("+++ invoke: %s %v", program, args)
	defer log.Printf("--- invoke end")
	cmd := osexec.Command(program, args...)

	// replace nil streams with default
	if fds.Out == nil {
		fds.Out = out
	}
	if fds.Err == nil {
		fds.Err = out
	}

	cmd.Stdout, cmd.Stderr = fds.Out, fds.Err
	err := cmd.Run()
	if err != nil {
		err = fmt.Errorf("executing %s %v failed: %v", program, args, err)
	}
	return err
}

// Exec is a convenience method to run programs with
// arguments and return their combined stdout/stderr
// output as bytes.
func Exec(program string, args ...string) ([]byte, error) {
	var b bytes.Buffer
	cmd := osexec.Command(program, args...)
	cmd.Stdout = &b
	cmd.Stderr = &b
	err := cmd.Run()
	if err != nil {
		err = fmt.Errorf("executing %s failed: %v", program, err)
	}
	return b.Bytes(), err
}

// ExecWithStdin pipes given ReadCloser's contents to the stdin of executed
// command and returns stdout as bytes and redirects stderr of executed command
// stderr of executing process.
func ExecWithStdin(in io.ReadCloser, program string, args ...string) ([]byte, error) {
	var b bytes.Buffer
	cmd := osexec.Command(program, args...)
	cmd.Stdin = in
	cmd.Stdout = &b
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		err = fmt.Errorf("executing %s failed: %v", program, err)
	}
	return b.Bytes(), err
}

repository: AzureMentor/azure-docker-extension

repo_name: AzureMentor/azure-docker-extension


text:
/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/effects/SkRuntimeEffect.h"
#include "tools/Resources.h"

#include <stddef.h>
#include <utility>

const char* SKSL_TEST_SRC = R"(
    void main(inout half4 color) {
        color.a = color.r*0.3 + color.g*0.6 + color.b*0.1;
        color.r = 0;
        color.g = 0;
        color.b = 0;
    }
)";

DEF_SIMPLE_GM(runtimecolorfilter, canvas, 512, 256) {
    auto img = GetResourceAsImage("images/mandrill_256.png");
    canvas->drawImage(img, 0, 0, nullptr);

    sk_sp<SkRuntimeEffect> effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_TEST_SRC)));

    auto cf1 = effect->makeColorFilter(nullptr);
    SkPaint p;
    p.setColorFilter(cf1);
    canvas->drawImage(img, 256, 0, &p);
}

repository: skui-org/skia

repo_name: skui-org/skia

extension: cpp


text:
require recipes-rose/images/rose-image-multimedia.bb

DESCRIPTION = "Kodi Mediacenter Image"

IMAGE_INSTALL += " \
    kodi \
    "

repository: rose-project/meta-gadgets

repo_name: rose-project/meta-gadgets


text:
SUMMARY = "Jalv is a simple but fully featured LV2 host for Jack"
HOMEPAGE = "http://drobilla.net/software/jalv"
LICENSE = "ISC"
LIC_FILES_CHKSUM = "file://COPYING;md5=f6c5b43b95e2c2f1a006d1310332a8fb"

inherit waf pkgconfig gtk-icon-cache

DEPENDS += " \
    qtbase-native \
    lv2 \
    lilv \
    serd \
    sord \
    sratom \
    suil \
    jack \
    gtkmm \
    gtk+3 \
    qtbase \
"

SRC_URI = " \
    gitsm://gitlab.com/drobilla/jalv.git;protocol=https;branch=master \
    file://0001-Fix-build-for-python3-only-environments.patch \
"
SRCREV = "9ab6e66c6ea7230f716b74d62c03fc5d19f56abe"
S = "${WORKDIR}/git"
PV = "1.6.6"

FILES:${PN} += " \
    ${libdir}/jack \
"

repository: schnitzeltony/meta-musicians

repo_name: schnitzeltony/meta-musicians

gha_language: BitBake


text:
require optee-test-fio.inc

SRCREV = "30efcbeaf8864d0f2a5c4be593a5411001fab31b"

SRC_URI += " \
    file://0001-os_test-disable-c-tests.patch \
    file://0001-regression-remove-7000-series.patch \
    file://0001-xtest-remove-compilation-of-regression_7000.c.patch \
"

repository: doanac/meta-lmp

repo_name: doanac/meta-lmp


text:
package main

import (
	"fmt"
	"strings"

	"github.com/docker/app/internal"
	"github.com/docker/cli/cli/command"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
// FIXME(vdemeester) use command.Cli interface
func newRootCmd(dockerCli *command.DockerCli) *cobra.Command {
	cmd := &cobra.Command{
		Use:          "docker-app",
		Short:        "Docker App Packages",
		Long:         `Build and deploy Docker applications.`,
		SilenceUsage: true,
		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			if internal.Debug {
				log.SetLevel(log.DebugLevel)
			}
			return nil
		},
	}
	cmd.PersistentFlags().BoolVar(&internal.Debug, "debug", false, "Enable debug mode")
	addCommands(cmd, dockerCli)
	return cmd
}

// addCommands adds all the commands from cli/command to the root command
func addCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
	cmd.AddCommand(
		deployCmd(dockerCli),
		helmCmd(),
		initCmd(),
		inspectCmd(dockerCli),
		lsCmd(),
		pushCmd(),
		renderCmd(dockerCli),
		saveCmd(dockerCli),
		versionCmd(dockerCli),
	)
	if internal.Experimental == "on" {
		cmd.AddCommand(
			imageAddCmd(),
			imageLoadCmd(),
			loadCmd(),
			mergeCmd(dockerCli),
			packCmd(dockerCli),
			pullCmd(),
			splitCmd(),
			unpackCmd(),
		)
	}
}

func firstOrEmpty(list []string) string {
	if len(list) != 0 {
		return list[0]
	}
	return ""
}

func parseSettings(s []string) (map[string]string, error) {
	d := make(map[string]string)
	for _, v := range s {
		kv := strings.SplitN(v, "=", 2)
		if len(kv) != 2 {
			return nil, fmt.Errorf("Missing '=' in setting '%s', expected KEY=VALUE", v)
		}
		if _, ok := d[kv[0]]; ok {
			return nil, fmt.Errorf("Duplicate command line setting: '%s'", kv[0])
		}
		d[kv[0]] = kv[1]
	}
	return d, nil
}

repository: shin-/app

repo_name: shin-/app


text:
package cortical_test

import (
	"context"
	"fmt"
	"github.com/gorilla/websocket"
	"github.com/owulveryck/cortical"
	"log"
	"net/http"
)

// echo is a dummy type that reads a message, and send back an "ack"
type echo struct{}

func new() *echo {
	return &echo{}
}

// NewCortex is filling the  ...
func (e *echo) NewCortex(ctx context.Context) (cortical.GetInfoFromCortexFunc, cortical.SendInfoToCortex) {
	c := make(chan []byte)
	return func(ctx context.Context) chan []byte {
			return c
		}, func(ctx context.Context, b *[]byte) {
			c <- *b
		}
}

func Example() {
	brain := &cortical.Cortical{
		Upgrader: websocket.Upgrader{},
		Cortexes: []cortical.Cortex{new()},
	}
	http.HandleFunc("/ws", brain.ServeWS)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, index)
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

}

var index = `

	<title>demo</title>

`

repository: owulveryck/cortical

repo_name: owulveryck/cortical


text:
@inproceedings{Encalada_Espinoza-Andaluz_2020,
 author = {Encalada, Angel and Espinoza-Andaluz, Mayken},
 booktitle = {2020 IEEE ANDESCON},
 doi = {10.1109/ANDESCON50619.2020.9272133},
 isbn = {9781728193656},
 month = {Oct},
 pages = {1–6},
 place = {Quito, Ecuador},
 publisher = {IEEE},
 title = {Compression Effects on Mass Transport Phenomena in digitally generated PEFC Gas Diffusion Layers by using OpenPNM},
 url = {https://ieeexplore.ieee.org/document/9272133/},
 year = {2020}
}

repository: angelswat/academic-kickstart

repo_name: angelswat/academic-kickstart

gha_language: Shell


text:
package ietf

import (
    "runtime"
    "path"
)

func GetCapabilities() map[string]string {
    caps := make(map[string]string)
    caps["iana-crypt-hash"] = "2014-08-06"
    caps["iana-if-type"] = "2014-05-08"
    caps["ietf-diffserv-action"] = "2015-04-07"
    caps["ietf-diffserv-classifier"] = "2015-04-07"
    caps["ietf-diffserv-policy"] = "2015-04-07"
    caps["ietf-diffserv-target"] = "2015-04-07"
    caps["ietf-event-notifications"] = "2016-10-27"
    caps["ietf-inet-types"] = "2013-07-15"
    caps["ietf-interfaces"] = "2014-05-08"
    caps["ietf-interfaces-ext"] = "None"
    caps["ietf-ip"] = "2014-06-16"
    caps["ietf-ipv4-unicast-routing"] = "2015-05-25"
    caps["ietf-ipv6-unicast-routing"] = "2015-05-25"
    caps["ietf-key-chain"] = "2015-02-24"
    caps["ietf-netconf"] = "2011-06-01"
    caps["ietf-netconf-acm"] = "2012-02-22"
    caps["ietf-netconf-monitoring"] = "2010-10-04"
    caps["ietf-netconf-notifications"] = "2012-02-06"
    caps["ietf-netconf-with-defaults"] = "2011-06-01"
    caps["ietf-ospf"] = "2015-03-09"
    caps["ietf-restconf-monitoring"] = "2016-08-15"
    caps["ietf-routing"] = "2015-05-25"
    caps["ietf-syslog-types"] = "2015-11-09"
    caps["ietf-yang-library"] = "2016-06-21"
    caps["ietf-yang-push"] = "2016-10-28"
    caps["ietf-yang-smiv2"] = "2012-06-22"
    caps["ietf-yang-types"] = "2013-07-15"
    caps["policy-types"] = "2013-10-07"
    return caps
}

func GetNamespaces() map[string]string {
    namespaces := make(map[string]string)
    namespaces["iana-crypt-hash"] = "urn:ietf:params:xml:ns:yang:iana-crypt-hash"
    namespaces["iana-if-type"] = "urn:ietf:params:xml:ns:yang:iana-if-type"
    namespaces["ietf-diffserv-action"] = "urn:ietf:params:xml:ns:yang:ietf-diffserv-action"
    namespaces["ietf-diffserv-classifier"] = "urn:ietf:params:xml:ns:yang:ietf-diffserv-classifier"
    namespaces["ietf-diffserv-policy"] = "urn:ietf:params:xml:ns:yang:ietf-diffserv-policy"
    namespaces["ietf-diffserv-target"] = "urn:ietf:params:xml:ns:yang:ietf-diffserv-target"
    namespaces["ietf-event-notifications"] = "urn:ietf:params:xml:ns:yang:ietf-event-notifications"
    namespaces["ietf-inet-types"] = "urn:ietf:params:xml:ns:yang:ietf-inet-types"
    namespaces["ietf-interfaces"] = "urn:ietf:params:xml:ns:yang:ietf-interfaces"
    namespaces["ietf-interfaces-ext"] = "urn:ietf:params:xml:ns:yang:ietf-interfaces-ext"
    namespaces["ietf-ip"] = "urn:ietf:params:xml:ns:yang:ietf-ip"
    namespaces["ietf-ipv4-unicast-routing"] = "urn:ietf:params:xml:ns:yang:ietf-ipv4-unicast-routing"
    namespaces["ietf-ipv6-unicast-routing"] = "urn:ietf:params:xml:ns:yang:ietf-ipv6-unicast-routing"
    namespaces["ietf-key-chain"] = "urn:ietf:params:xml:ns:yang:ietf-key-chain"
    namespaces["ietf-netconf"] = "urn:ietf:params:xml:ns:netconf:base:1.0"
    namespaces["ietf-netconf-acm"] = "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
    namespaces["ietf-netconf-monitoring"] = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"
    namespaces["ietf-netconf-notifications"] = "urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"
    namespaces["ietf-netconf-with-defaults"] = "urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults"
    namespaces["ietf-ospf"] = "urn:ietf:params:xml:ns:yang:ietf-ospf"
    namespaces["ietf-restconf-monitoring"] = "urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"
    namespaces["ietf-routing"] = "urn:ietf:params:xml:ns:yang:ietf-routing"
    namespaces["ietf-syslog-types"] = "urn:ietf:params:xml:ns:yang:ietf-syslog-types"
    namespaces["ietf-yang-library"] = "urn:ietf:params:xml:ns:yang:ietf-yang-library"
    namespaces["ietf-yang-push"] = "urn:ietf:params:xml:ns:yang:ietf-yang-push"
    namespaces["ietf-yang-smiv2"] = "urn:ietf:params:xml:ns:yang:ietf-yang-smiv2"
    namespaces["ietf-yang-types"] = "urn:ietf:params:xml:ns:yang:ietf-yang-types"
    namespaces["policy-types"] = "urn:ietf:params:xml:ns:yang:c3pl-types"
    return namespaces
}

func GetModelsPath() string {
    _, filename, _, ok := runtime.Caller(0)
    if !ok {
        panic("No caller information")
    }
    return path.Join(path.Dir(filename), "_yang")
}

repository: milanlenco/ydk-go

repo_name: milanlenco/ydk-go


text:
package dom

import (
	"github.com/dustismo/heavyfishdesign/dynmap"
	"github.com/dustismo/heavyfishdesign/path"
	"github.com/dustismo/heavyfishdesign/transforms"
)

type GroupComponentFactory struct{}

type GroupComponent struct {
	*BasicComponent
	components       []Component
	segmentOperators path.SegmentOperators
}

func (ccf GroupComponentFactory) CreateComponent(componentType string, mp *dynmap.DynMap, dc *DocumentContext) (Component, error) {
	factory := AppContext()
	dm := mp.Clone()
	components, err := factory.MakeComponents(dm.MustDynMapSlice("components", []*dynmap.DynMap{}), dc)
	if err != nil {
		return nil, err
	}
	dm.Put("components", ComponentsToDynMap(components))
	bc := factory.MakeBasicComponent(dm)
	bc.SetComponents(components)
	gc := &GroupComponent{
		BasicComponent:   bc,
		components:       components,
		segmentOperators: factory.SegmentOperators(),
	}
	for _, c := range components {
		c.SetParent(gc)
	}
	return gc, nil
}

// The list of component types this Factory should be used for
func (ccf GroupComponentFactory) ComponentTypes() []string {
	return []string{"group"}
}

func (cc *GroupComponent) Children() []Element {
	return CtoE(cc.components)
}

func (cc *GroupComponent) Render(ctx RenderContext) (path.Path, RenderContext, error) {
	cc.RenderStart(ctx)

	// render all the children then merge into one path.
	paths := []path.Path{}

	context := ctx.Clone()
	for _, e := range cc.components {
		p, c, err := e.Render(context)
		if err != nil {
			return p, c, err
		}
		paths = append(paths, p)
		context = c
		// find the new cursor location
		context.Cursor = path.PathCursor(p)
	}

	p := transforms.SimpleJoin{}.JoinPaths(paths...)
	return cc.HandleTransforms(cc, p, context)
}

repository: dustismo/heavyfishdesign

repo_name: dustismo/heavyfishdesign


text:
@inproceedings{vuong2020learnable,
  author={Tyler Vuong and Yangyang Xia and Richard M. Stern},
  title={Learnable Spectro-Temporal Receptive Fields for Robust Voice Type Discrimination},
  year=2020,
  month = oct,
  booktitle={Interspeech 2020},
  pages={1957--1961},
  publisher = {{ISCA}},
  doi={10.21437/Interspeech.2020-1878},
  url={http://dx.doi.org/10.21437/Interspeech.2020-1878}
}


text:
SUMMARY = "Automatically generates Rust FFI bindings to C and C++ libraries."
HOMEPAGE = "https://rust-lang.github.io/rust-bindgen/"
LICENSE = "BSD-3-Clause"

LIC_FILES_CHKSUM = "file://LICENSE;md5=0b9a98cb3dcdefcceb145324693fda9b"

inherit rust cargo cargo-update-recipe-crates

SRCREV = "ae6817256ac557981906e93a1f866349db85053e"
SRC_URI = "git://github.com/rust-lang/rust-bindgen;protocol=https;branch=main"

S = "${WORKDIR}/git"

require ${BPN}-crates.inc

do_install:append:class-native() {
	create_wrapper ${D}/${bindir}/bindgen LIBCLANG_PATH="${STAGING_LIBDIR_NATIVE}"
}

RDEPENDS:${PN} = "libclang"

BBCLASSEXTEND = "native"

repository: kraj/meta-clang

repo_name: kraj/meta-clang


text:
package config

import (
	"github.com/eurofurence/reg-attendee-service/docs"
	"github.com/stretchr/testify/require"
	"testing"
	"time"
)

func TestServerAddrWithAddressAndPort(t *testing.T) {
	docs.Description("ensure ServerAddr() returns the correct server address string, with address specified")
	configurationData = &Application{Logging: LoggingConfig{Severity: "DEBUG"}, Server: ServerConfig{
		Address: "localhost",
		Port:    "1234",
	}}
	require.Equal(t, "localhost:1234", ServerAddr(), "unexpected server address string")
}

func TestServerAddrWithOnlyPort(t *testing.T) {
	docs.Description("ensure ServerAddr() returns the correct server address string, with no address specified")
	configurationData = &Application{Logging: LoggingConfig{Severity: "DEBUG"}, Server: ServerConfig{
		Port: "1234",
	}}
	require.Equal(t, ":1234", ServerAddr(), "unexpected server address string")
}

func TestServerTimeouts(t *testing.T) {
	docs.Description("ensure ServerRead/Write/IdleTimout() return the correct timeouts")
	configurationData = &Application{Logging: LoggingConfig{Severity: "DEBUG"}, Server: ServerConfig{
		Address:      "localhost",
		Port:         "1234",
		ReadTimeout:  13,
		WriteTimeout: 17,
		IdleTimeout:  23,
	}}
	require.Equal(t, 13*time.Second, ServerReadTimeout())
	require.Equal(t, 17*time.Second, ServerWriteTimeout())
	require.Equal(t, 23*time.Second, ServerIdleTimeout())
}

func TestDatabaseMysqlConnectString(t *testing.T) {
	docs.Description("ensure DatabaseMysqlConnectString() returns the correct mysql connect string")
	configurationData = &Application{
		Logging: LoggingConfig{Severity: "DEBUG"},
		Database: DatabaseConfig{
			Use:      "mysql",
			Username: "demouser",
			Password: "demopw",
			Database: "tcp(localhost:3306)/dbname",
			Parameters: []string{
				"charset=utf8mb4",
				"timeout=30s"},
		}}
	require.Equal(t, "demouser:demopw@tcp(localhost:3306)/dbname?charset=utf8mb4&timeout=30s", DatabaseMysqlConnectString(), "unexpected mysql db connection string")
}

func TestMigrateDatabase(t *testing.T) {
	docs.Description("ensure migrate database flag is returned correctly")
	dbMigrate = true
	require.Equal(t, true, MigrateDatabase(), "unexpected return value")

	dbMigrate = false
	require.Equal(t, false, MigrateDatabase(), "unexpected return value")
}

repository: eurofurence/reg-attendee-service

repo_name: eurofurence/reg-attendee-service