<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkAndroidSDKCanvas.h"

#include "SkColorFilter.h"
#include "SkDrawLooper.h"
#include "SkPaint.h"
#include "SkPathEffect.h"
#include "SkShader.h"
#include "SkSurface.h"
#include "SkTLazy.h"

namespace {

/** Discard SkShaders not exposed by the Android Java API. */

void CheckShader(SkPaint* paint) {
    SkShader* shader = paint->getShader();
    if (!shader) {
        return;
    }

    if (shader->isAImage()) {
        return;
    }
    if (shader->asACompose(nullptr)) {
        return;
    }
    SkShader::GradientType gtype = shader->asAGradient(nullptr);
    if (gtype == SkShader::kLinear_GradientType ||
        gtype == SkShader::kRadial_GradientType ||
        gtype == SkShader::kSweep_GradientType) {
        return;
    }
    paint->setShader(nullptr);
}

void Filter(SkPaint* paint) {

    uint32_t flags = paint->getFlags();
    flags &= ~SkPaint::kLCDRenderText_Flag;
    paint->setFlags(flags);

    // Android doesn't support blend modes above kLighten_Mode
    if (paint->getBlendMode() > SkBlendMode::kLighten) {
        paint->setBlendMode(SkBlendMode::kSrcOver);
    }

    // Force bilinear scaling or none
    if (paint->getFilterQuality() != kNone_SkFilterQuality) {
        paint->setFilterQuality(kLow_SkFilterQuality);
    }

    CheckShader(paint);

    // Android SDK only supports mode & matrix color filters
    // (and, again, no modes above kLighten_Mode).
    SkColorFilter* cf = paint->getColorFilter();
    if (cf) {
        SkColor color;
        SK_XFERMODE_MODE_PARAM mode;
        SkScalar srcColorMatrix[20];
        bool isMode = cf->asColorMode(&color, &mode);
        if (isMode && (int)mode > (int)SkBlendMode::kLighten) {
            paint->setColorFilter(
                SkColorFilter::MakeModeFilter(color, SkBlendMode::kSrcOver));
        } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
            paint->setColorFilter(nullptr);
        }
    }

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    SkPathEffect* pe = paint->getPathEffect();
    if (pe && !pe->exposedInAndroidJavaAPI()) {
        paint->setPathEffect(nullptr);
    }
#endif

    // TODO: Android doesn't support all the flags that can be passed to
    // blur filters; we need plumbing to get them out.

    paint->setImageFilter(nullptr);
    paint->setLooper(nullptr);
};

}  // namespace

#define FILTER(p)             \
    SkPaint filteredPaint(p); \
    Filter(&filteredPaint);

#define FILTER_PTR(p)                          \
    SkTLazy<SkPaint> lazyPaint;                \
    SkPaint* filteredPaint = (SkPaint*) p;     \
    if (p) {                                   \
        filteredPaint = lazyPaint.set(*p);     \
        Filter(filteredPaint);                 \
    }

SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { }

void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }

void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPaint(filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
                                               size_t count,
                                               const SkPoint pts[],
                                               const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawOval(r, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawArc(const SkRect& r, SkScalar startAngle, SkScalar sweepAngle,
                                   bool useCenter, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawArc(r, startAngle, sweepAngle, useCenter, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawRect(r, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawRRect(r, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPath(path, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
                                               SkScalar left,
                                               SkScalar top,
                                               const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
                                                   const SkRect* src,
                                                   const SkRect& dst,
                                                   const SkPaint* paint,
                                                   SkCanvas::SrcRectConstraint constraint) {
    FILTER_PTR(paint);
    fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
}
void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
                                                   const SkIRect& center,
                                                   const SkRect& dst,
                                                   const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
                                                 int vertexCount,
                                                 const SkPoint vertices[],
                    const SkPoint texs[], const SkColor colors[], SK_XFERMODE_PARAM xMode,
                    const uint16_t indices[], int indexCount,
                    const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
                               xMode, indices, indexCount, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
                                               const SkRRect& inner,
                                               const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawDRRect(outer, inner, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawText(const void* text,
                                             size_t byteLength,
                                             SkScalar x,
                                             SkScalar y,
                                             const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPosText(const void* text,
                                                size_t byteLength,
                                                const SkPoint pos[],
                                                const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
                                                 size_t byteLength,
                                                 const SkScalar xpos[],
                                                 SkScalar constY,
                                                 const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
                                          size_t byteLength,
                                          const SkPath& path,
                                          const SkMatrix* matrix,
                                          const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
                                           const SkRSXform xform[], const SkRect* cull,
                                           const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawTextRSXform(text, byteLength, xform, cull, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
                                                 SkScalar x,
                                                 SkScalar y,
                                                 const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
                                              const SkColor colors[4],
                                              const SkPoint texCoords[4],
                                              SK_XFERMODE_PARAM xmode,
                                              const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
                                              SkScalar x,
                                              SkScalar y,
                                              const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawImage(image, x, y, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
                                         const SkRect* in,
                                         const SkRect& out,
                                         const SkPaint* paint,
                                         SrcRectConstraint constraint) {
    FILTER_PTR(paint);
    fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
}

void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
                                       const SkMatrix* matrix,
                                       const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawPicture(picture, matrix, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
                                     const SkRSXform xform[],
                                     const SkRect tex[],
                                     const SkColor colors[],
                                     int count,
                                     SK_XFERMODE_MODE_PARAM mode,
                                     const SkRect* cullRect,
                                     const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
                            filteredPaint);
}

void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
                                         const SkIRect& center,
                                         const SkRect& dst,
                                         const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
    fProxyTarget->drawDrawable(drawable, matrix);
}

SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
    return fProxyTarget->getBaseLayerSize();
}
bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
    return fProxyTarget->getClipBounds(rect);
}
bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
    return fProxyTarget->getClipDeviceBounds(rect);
}

bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }

sk_sp<SkSurface> SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
                                                  const SkSurfaceProps& props) {
    return fProxyTarget->makeSurface(info, &props);
}

bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
    return fProxyTarget->peekPixels(pmap);
}

bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
    SkASSERT(pmap);
    SkImageInfo info;
    size_t rowBytes;
    const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
    if (addr) {
        pmap->reset(info, addr, rowBytes);
        return true;
    }
    return false;
}

void SkAndroidSDKCanvas::willSave() {
    fProxyTarget->save();
}

SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
    fProxyTarget->saveLayer(rec);
    return SkCanvas::kNoLayer_SaveLayerStrategy;
}

void SkAndroidSDKCanvas::willRestore() {
    fProxyTarget->restore();
}

void SkAndroidSDKCanvas::didRestore() { }

void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
    fProxyTarget->concat(m);
}

void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
    fProxyTarget->setMatrix(m);
}

void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
                                             ClipOp op,
                                             ClipEdgeStyle style) {
    fProxyTarget->clipRect(rect, op, style);
}

void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
                                              ClipOp op,
                                              ClipEdgeStyle style) {
    fProxyTarget->clipRRect(rrect, op, style);
}

void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
                                             ClipOp op,
                                             ClipEdgeStyle style) {
    fProxyTarget->clipPath(path, op, style);
}

void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, ClipOp op) {
    fProxyTarget->clipRegion(region, op);
}

void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
<commit_msg>add include to remove legacy flag<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkAndroidSDKCanvas.h"

#include "SkColorFilter.h"
#include "SkDrawLooper.h"
#include "SkImageFilter.h"
#include "SkPaint.h"
#include "SkPathEffect.h"
#include "SkShader.h"
#include "SkSurface.h"
#include "SkTLazy.h"

namespace {

/** Discard SkShaders not exposed by the Android Java API. */

void CheckShader(SkPaint* paint) {
    SkShader* shader = paint->getShader();
    if (!shader) {
        return;
    }

    if (shader->isAImage()) {
        return;
    }
    if (shader->asACompose(nullptr)) {
        return;
    }
    SkShader::GradientType gtype = shader->asAGradient(nullptr);
    if (gtype == SkShader::kLinear_GradientType ||
        gtype == SkShader::kRadial_GradientType ||
        gtype == SkShader::kSweep_GradientType) {
        return;
    }
    paint->setShader(nullptr);
}

void Filter(SkPaint* paint) {

    uint32_t flags = paint->getFlags();
    flags &= ~SkPaint::kLCDRenderText_Flag;
    paint->setFlags(flags);

    // Android doesn't support blend modes above kLighten_Mode
    if (paint->getBlendMode() > SkBlendMode::kLighten) {
        paint->setBlendMode(SkBlendMode::kSrcOver);
    }

    // Force bilinear scaling or none
    if (paint->getFilterQuality() != kNone_SkFilterQuality) {
        paint->setFilterQuality(kLow_SkFilterQuality);
    }

    CheckShader(paint);

    // Android SDK only supports mode & matrix color filters
    // (and, again, no modes above kLighten_Mode).
    SkColorFilter* cf = paint->getColorFilter();
    if (cf) {
        SkColor color;
        SK_XFERMODE_MODE_PARAM mode;
        SkScalar srcColorMatrix[20];
        bool isMode = cf->asColorMode(&color, &mode);
        if (isMode && (int)mode > (int)SkBlendMode::kLighten) {
            paint->setColorFilter(
                SkColorFilter::MakeModeFilter(color, SkBlendMode::kSrcOver));
        } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) {
            paint->setColorFilter(nullptr);
        }
    }

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    SkPathEffect* pe = paint->getPathEffect();
    if (pe && !pe->exposedInAndroidJavaAPI()) {
        paint->setPathEffect(nullptr);
    }
#endif

    // TODO: Android doesn't support all the flags that can be passed to
    // blur filters; we need plumbing to get them out.

    paint->setImageFilter(nullptr);
    paint->setLooper(nullptr);
};

}  // namespace

#define FILTER(p)             \
    SkPaint filteredPaint(p); \
    Filter(&filteredPaint);

#define FILTER_PTR(p)                          \
    SkTLazy<SkPaint> lazyPaint;                \
    SkPaint* filteredPaint = (SkPaint*) p;     \
    if (p) {                                   \
        filteredPaint = lazyPaint.set(*p);     \
        Filter(filteredPaint);                 \
    }

SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { }

void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; }

void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPaint(filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode,
                                               size_t count,
                                               const SkPoint pts[],
                                               const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPoints(pMode, count, pts, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawOval(r, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawArc(const SkRect& r, SkScalar startAngle, SkScalar sweepAngle,
                                   bool useCenter, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawArc(r, startAngle, sweepAngle, useCenter, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawRect(r, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawRRect(r, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPath(path, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap,
                                               SkScalar left,
                                               SkScalar top,
                                               const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
                                                   const SkRect* src,
                                                   const SkRect& dst,
                                                   const SkPaint* paint,
                                                   SkCanvas::SrcRectConstraint constraint) {
    FILTER_PTR(paint);
    fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint);
}
void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
                                                   const SkIRect& center,
                                                   const SkRect& dst,
                                                   const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode,
                                                 int vertexCount,
                                                 const SkPoint vertices[],
                    const SkPoint texs[], const SkColor colors[], SK_XFERMODE_PARAM xMode,
                    const uint16_t indices[], int indexCount,
                    const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors,
                               xMode, indices, indexCount, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer,
                                               const SkRRect& inner,
                                               const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawDRRect(outer, inner, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawText(const void* text,
                                             size_t byteLength,
                                             SkScalar x,
                                             SkScalar y,
                                             const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawText(text, byteLength, x, y, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPosText(const void* text,
                                                size_t byteLength,
                                                const SkPoint pos[],
                                                const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
                                                 size_t byteLength,
                                                 const SkScalar xpos[],
                                                 SkScalar constY,
                                                 const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
                                          size_t byteLength,
                                          const SkPath& path,
                                          const SkMatrix* matrix,
                                          const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
                                           const SkRSXform xform[], const SkRect* cull,
                                           const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawTextRSXform(text, byteLength, xform, cull, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
                                                 SkScalar x,
                                                 SkScalar y,
                                                 const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawTextBlob(blob, x, y, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12],
                                              const SkColor colors[4],
                                              const SkPoint texCoords[4],
                                              SK_XFERMODE_PARAM xmode,
                                              const SkPaint& paint) {
    FILTER(paint);
    fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawImage(const SkImage* image,
                                              SkScalar x,
                                              SkScalar y,
                                              const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawImage(image, x, y, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image,
                                         const SkRect* in,
                                         const SkRect& out,
                                         const SkPaint* paint,
                                         SrcRectConstraint constraint) {
    FILTER_PTR(paint);
    fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint);
}

void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
                                       const SkMatrix* matrix,
                                       const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawPicture(picture, matrix, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas,
                                     const SkRSXform xform[],
                                     const SkRect tex[],
                                     const SkColor colors[],
                                     int count,
                                     SK_XFERMODE_MODE_PARAM mode,
                                     const SkRect* cullRect,
                                     const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect,
                            filteredPaint);
}

void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image,
                                         const SkIRect& center,
                                         const SkRect& dst,
                                         const SkPaint* paint) {
    FILTER_PTR(paint);
    fProxyTarget->drawImageNine(image, center, dst, filteredPaint);
}

void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
    fProxyTarget->drawDrawable(drawable, matrix);
}

SkISize SkAndroidSDKCanvas::getBaseLayerSize() const {
    return fProxyTarget->getBaseLayerSize();
}
bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const {
    return fProxyTarget->getClipBounds(rect);
}
bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const {
    return fProxyTarget->getClipDeviceBounds(rect);
}

bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); }
bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); }

sk_sp<SkSurface> SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info,
                                                  const SkSurfaceProps& props) {
    return fProxyTarget->makeSurface(info, &props);
}

bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) {
    return fProxyTarget->peekPixels(pmap);
}

bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
    SkASSERT(pmap);
    SkImageInfo info;
    size_t rowBytes;
    const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr);
    if (addr) {
        pmap->reset(info, addr, rowBytes);
        return true;
    }
    return false;
}

void SkAndroidSDKCanvas::willSave() {
    fProxyTarget->save();
}

SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
    fProxyTarget->saveLayer(rec);
    return SkCanvas::kNoLayer_SaveLayerStrategy;
}

void SkAndroidSDKCanvas::willRestore() {
    fProxyTarget->restore();
}

void SkAndroidSDKCanvas::didRestore() { }

void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) {
    fProxyTarget->concat(m);
}

void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) {
    fProxyTarget->setMatrix(m);
}

void SkAndroidSDKCanvas::onClipRect(const SkRect& rect,
                                             ClipOp op,
                                             ClipEdgeStyle style) {
    fProxyTarget->clipRect(rect, op, style);
}

void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect,
                                              ClipOp op,
                                              ClipEdgeStyle style) {
    fProxyTarget->clipRRect(rrect, op, style);
}

void SkAndroidSDKCanvas::onClipPath(const SkPath& path,
                                             ClipOp op,
                                             ClipEdgeStyle style) {
    fProxyTarget->clipPath(path, op, style);
}

void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, ClipOp op) {
    fProxyTarget->clipRegion(region, op);
}

void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); }
<|endoftext|>


<commit_before>#include "HeatTransferFromHeatStructure1Phase.h"
#include "FlowChannel1Phase.h"
#include "HeatStructure.h"
#include "FlowModelSinglePhase.h"
#include "FlowModelTwoPhase.h"
#include "KDTree.h"
#include "THMMesh.h"
#include "libmesh/fe_interface.h"

registerMooseObject("THMApp", HeatTransferFromHeatStructure1Phase);

template <>
InputParameters
validParams<HeatTransferFromHeatStructure1Phase>()
{
  InputParameters params = validParams<HeatTransferFromTemperature1Phase>();
  params.addRequiredParam<std::string>("hs", "The name of the heat structure component");
  MooseEnum hs_sides("top bottom");
  params.addRequiredParam<MooseEnum>("hs_side", hs_sides, "The side of the heat structure");
  params.addClassDescription("Connects a 1-phase flow channel and a heat structure");
  return params;
}

HeatTransferFromHeatStructure1Phase::HeatTransferFromHeatStructure1Phase(
    const InputParameters & parameters)
  : HeatTransferFromTemperature1Phase(parameters),
    _hs_name(getParam<std::string>("hs")),
    _hs_side(getParam<MooseEnum>("hs_side"))
{
}

void
HeatTransferFromHeatStructure1Phase::checkFlowChannelAlignment() const
{
  const FlowChannel1Phase & flow_channel =
      getComponentByName<FlowChannel1Phase>(_flow_channel_name);

  // master element centroids
  std::vector<Point> master_points;
  // element ids corresponding to the centroids in `master_points`
  std::vector<dof_id_type> master_elem_ids;
  // local side number corresponding to the element id in `master_elem_ids`
  std::vector<dof_id_type> master_elem_sides;
  // slave element centroids
  std::vector<Point> slave_points;
  // element ids corresponding to the centroids in `slave_points`
  std::vector<dof_id_type> slave_elem_ids;
  /// Map of the element ID and its nearest element ID
  std::map<dof_id_type, dof_id_type> nearest_elem_ids;
  /// Map of the element ID and local side number of the nearest element
  std::map<dof_id_type, unsigned int> nearest_elem_side;

  BoundaryID master_bnd_id = _mesh.getBoundaryID(getMasterSideName());
  BoundaryID slave_bnd_id = _mesh.getBoundaryID(getSlaveSideName());

  ConstBndElemRange & range = *_mesh.getBoundaryElementRange();
  for (const auto & belem : range)
  {
    const Elem * elem = belem->_elem;
    BoundaryID boundary_id = belem->_bnd_id;

    if (boundary_id == master_bnd_id)
    {
      // 2D elements
      master_elem_ids.push_back(elem->id());
      master_elem_sides.push_back(belem->_side);
      master_points.push_back(elem->centroid());
      nearest_elem_side.insert(std::pair<dof_id_type, unsigned int>(elem->id(), belem->_side));
    }
    else if (boundary_id == slave_bnd_id)
    {
      if (std::find(slave_elem_ids.begin(), slave_elem_ids.end(), elem->id()) ==
          slave_elem_ids.end())
      {
        // 1D elements
        slave_elem_ids.push_back(elem->id());
        slave_points.push_back(elem->centroid());
      }
    }
  }

  if (master_points.size() > 0 && slave_points.size() > 0)
  {
    // find the master elements that are nearest to the slave elements
    KDTree kd_tree(master_points, _mesh.getMaxLeafSize());
    for (std::size_t i = 0; i < slave_points.size(); i++)
    {
      unsigned int patch_size = 1;
      std::vector<std::size_t> return_index(patch_size);
      kd_tree.neighborSearch(slave_points[i], patch_size, return_index);

      nearest_elem_ids.insert(
          std::pair<dof_id_type, dof_id_type>(slave_elem_ids[i], master_elem_ids[return_index[0]]));
      nearest_elem_ids.insert(
          std::pair<dof_id_type, dof_id_type>(master_elem_ids[return_index[0]], slave_elem_ids[i]));
    }

    // Go over all elements in the flow channel. Take the center of each element and project it onto
    // the heat structure side. Then check that the projected location on the heat structure matches
    // the location of the original center of the flow channel element
    const std::vector<unsigned int> & fch_elem_ids = flow_channel.getElementIDs();
    for (const auto & elem_id : fch_elem_ids)
    {
      const Elem * elem = _mesh.elemPtr(elem_id);
      Point center_pt = elem->centroid();

      const dof_id_type & hs_elem_id = nearest_elem_ids.at(elem_id);
      const unsigned int & hs_elem_side = nearest_elem_side.at(hs_elem_id);
      const Elem * neighbor = _mesh.elemPtr(hs_elem_id);
      const Elem * neighbor_side_elem = neighbor->build_side_ptr(hs_elem_side).release();
      unsigned int neighbor_dim = neighbor_side_elem->dim();
      Point ref_pt =
          FEInterface::inverse_map(neighbor_dim, FEType(), neighbor_side_elem, center_pt);
      Point hs_pt = FEInterface::map(neighbor_dim, FEType(), neighbor_side_elem, ref_pt);
      delete neighbor_side_elem;

      if (!center_pt.absolute_fuzzy_equals(hs_pt))
      {
        logError("The centers of the elements of flow channel '",
                 _flow_channel_name,
                 "' do not equal the centers of the specified heat structure side.");
        break;
      }
    }
  }
}

void
HeatTransferFromHeatStructure1Phase::check() const
{
  HeatTransferFromTemperature1Phase::check();

  checkComponentOfTypeExistsByName<HeatStructure>(_hs_name);

  if (hasComponentByName<HeatStructure>(_hs_name))
  {
    const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
    if (hs.getDimension() == 1)
      logError("1D heat structures cannot be used; 2D heat structures must be used instead.");

    const Real & P_hs = hs.getUnitPerimeter(_hs_side);
    if (MooseUtils::absoluteFuzzyEqual(P_hs, 0.))
      logError("'hs_side' parameter is set to '",
               _hs_side,
               "', but this side of the heat structure '",
               _hs_name,
               "' has radius of zero.");
  }

  if (hasComponentByName<HeatStructure>(_hs_name) &&
      hasComponentByName<FlowChannel1Phase>(_flow_channel_name))
  {
    const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
    const FlowChannel1Phase & flow_channel =
        getComponentByName<FlowChannel1Phase>(_flow_channel_name);

    if (hs.getNumElems() != flow_channel.getNumElems())
      logError("The number of elements in component '",
               _flow_channel_name,
               "' is ",
               flow_channel.getNumElems(),
               ", but the number of axial elements in component '",
               _hs_name,
               "' is ",
               hs.getNumElems(),
               ". They must be the same.");

    if (hs.getLength() != flow_channel.getLength())
      logError("The length of component '",
               _flow_channel_name,
               "' is ",
               flow_channel.getLength(),
               ", but the length of component '",
               _hs_name,
               "' is ",
               hs.getLength(),
               ". They must be the same.");

    checkFlowChannelAlignment();
  }
}

void
HeatTransferFromHeatStructure1Phase::addVariables()
{
  HeatTransferFromTemperature1Phase::addVariables();

  // wall temperature initial condition
  if (!_app.isRestarting())
  {
    const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
    _sim.addFunctionIC(_T_wall_name, hs.getInitialT(), _flow_channel_name);
  }
}

void
HeatTransferFromHeatStructure1Phase::addMooseObjects()
{
  HeatTransferFromTemperature1Phase::addMooseObjects();

  ExecFlagEnum execute_on(MooseUtils::getDefaultExecFlagEnum());
  execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};

  const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
  const FlowChannel1Phase & flow_channel =
      getComponentByName<FlowChannel1Phase>(_flow_channel_name);

  const UserObjectName heat_flux_uo_name = genName(name(), "heat_flux_uo");
  {
    const std::string class_name = "HeatFluxFromHeatStructure3EqnUserObject";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<std::vector<SubdomainName>>("block") = flow_channel.getSubdomainNames();
    params.set<std::vector<BoundaryName>>("slave_boundary") = {getSlaveSideName()};
    params.set<BoundaryName>("master_boundary") = getMasterSideName();
    params.set<std::vector<VariableName>>("T_wall") = {_T_wall_name};
    params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
    params.set<MaterialPropertyName>("Hw") = _Hw_1phase_name;
    params.set<MaterialPropertyName>("T") = FlowModelSinglePhase::TEMPERATURE;
    params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
    params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
    params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
    params.set<ExecFlagEnum>("execute_on") = execute_on;
    _sim.addUserObject(class_name, heat_flux_uo_name, params);
  }

  {
    const std::string class_name = "OneD3EqnEnergyHeatFlux";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<std::vector<SubdomainName>>("block") = flow_channel.getSubdomainNames();
    params.set<NonlinearVariableName>("variable") = FlowModelSinglePhase::RHOEA;
    params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
    params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
    params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
    params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
    params.set<UserObjectName>("q_uo") = heat_flux_uo_name;
    _sim.addKernel(class_name, genName(name(), "heat_flux_kernel"), params);
  }

  {
    const std::string class_name = "HeatFlux3EqnBC";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<std::vector<BoundaryName>>("boundary") = {getMasterSideName()};
    params.set<NonlinearVariableName>("variable") = HeatConductionModel::TEMPERATURE;
    params.set<UserObjectName>("q_uo") = heat_flux_uo_name;
    params.set<Real>("P_hs_unit") = hs.getUnitPerimeter(_hs_side);
    params.set<unsigned int>("n_unit") = hs.getNumberOfUnits();
    params.set<bool>("hs_coord_system_is_cylindrical") = hs.isCylindrical();
    params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
    params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
    params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
    params.set<std::vector<VariableName>>("T_wall") = {HeatConductionModel::TEMPERATURE};
    _sim.addBoundaryCondition(class_name, genName(name(), "heat_flux_bc"), params);
  }

  // Transfer the temperature of the solid onto the flow channel
  {
    std::string class_name = "VariableValueTransferAux";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<AuxVariableName>("variable") = _T_wall_name;
    params.set<std::vector<BoundaryName>>("boundary") = {getSlaveSideName()};
    params.set<BoundaryName>("paired_boundary") = getMasterSideName();
    params.set<std::vector<VariableName>>("paired_variable") =
        std::vector<VariableName>(1, HeatConductionModel::TEMPERATURE);
    _sim.addAuxBoundaryCondition(class_name, genName(name(), "T_wall_transfer"), params);
  }
}

const BoundaryName &
HeatTransferFromHeatStructure1Phase::getMasterSideName() const
{
  const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);

  switch (_hs_side)
  {
    case 0:
      if (hs.getTopBoundaryNames().size() > 0)
        return hs.getTopBoundaryNames()[0];
      else
        return THMMesh::INVALID_BOUNDARY_ID;

    case 1:
      if (hs.getBottomBoundaryNames().size() > 0)
        return hs.getBottomBoundaryNames()[0];
      else
        return THMMesh::INVALID_BOUNDARY_ID;

    default:
      mooseError(name(), ": Unknown side specified in the 'hs_side' parameter.");
  }
}

const BoundaryName &
HeatTransferFromHeatStructure1Phase::getSlaveSideName() const
{
  const FlowChannel1Phase & flow_channel =
      getComponentByName<FlowChannel1Phase>(_flow_channel_name);
  return flow_channel.getNodesetName();
}
<commit_msg>Removing unused #include<commit_after>#include "HeatTransferFromHeatStructure1Phase.h"
#include "FlowChannel1Phase.h"
#include "HeatStructure.h"
#include "FlowModelSinglePhase.h"
#include "KDTree.h"
#include "THMMesh.h"
#include "libmesh/fe_interface.h"

registerMooseObject("THMApp", HeatTransferFromHeatStructure1Phase);

template <>
InputParameters
validParams<HeatTransferFromHeatStructure1Phase>()
{
  InputParameters params = validParams<HeatTransferFromTemperature1Phase>();
  params.addRequiredParam<std::string>("hs", "The name of the heat structure component");
  MooseEnum hs_sides("top bottom");
  params.addRequiredParam<MooseEnum>("hs_side", hs_sides, "The side of the heat structure");
  params.addClassDescription("Connects a 1-phase flow channel and a heat structure");
  return params;
}

HeatTransferFromHeatStructure1Phase::HeatTransferFromHeatStructure1Phase(
    const InputParameters & parameters)
  : HeatTransferFromTemperature1Phase(parameters),
    _hs_name(getParam<std::string>("hs")),
    _hs_side(getParam<MooseEnum>("hs_side"))
{
}

void
HeatTransferFromHeatStructure1Phase::checkFlowChannelAlignment() const
{
  const FlowChannel1Phase & flow_channel =
      getComponentByName<FlowChannel1Phase>(_flow_channel_name);

  // master element centroids
  std::vector<Point> master_points;
  // element ids corresponding to the centroids in `master_points`
  std::vector<dof_id_type> master_elem_ids;
  // local side number corresponding to the element id in `master_elem_ids`
  std::vector<dof_id_type> master_elem_sides;
  // slave element centroids
  std::vector<Point> slave_points;
  // element ids corresponding to the centroids in `slave_points`
  std::vector<dof_id_type> slave_elem_ids;
  /// Map of the element ID and its nearest element ID
  std::map<dof_id_type, dof_id_type> nearest_elem_ids;
  /// Map of the element ID and local side number of the nearest element
  std::map<dof_id_type, unsigned int> nearest_elem_side;

  BoundaryID master_bnd_id = _mesh.getBoundaryID(getMasterSideName());
  BoundaryID slave_bnd_id = _mesh.getBoundaryID(getSlaveSideName());

  ConstBndElemRange & range = *_mesh.getBoundaryElementRange();
  for (const auto & belem : range)
  {
    const Elem * elem = belem->_elem;
    BoundaryID boundary_id = belem->_bnd_id;

    if (boundary_id == master_bnd_id)
    {
      // 2D elements
      master_elem_ids.push_back(elem->id());
      master_elem_sides.push_back(belem->_side);
      master_points.push_back(elem->centroid());
      nearest_elem_side.insert(std::pair<dof_id_type, unsigned int>(elem->id(), belem->_side));
    }
    else if (boundary_id == slave_bnd_id)
    {
      if (std::find(slave_elem_ids.begin(), slave_elem_ids.end(), elem->id()) ==
          slave_elem_ids.end())
      {
        // 1D elements
        slave_elem_ids.push_back(elem->id());
        slave_points.push_back(elem->centroid());
      }
    }
  }

  if (master_points.size() > 0 && slave_points.size() > 0)
  {
    // find the master elements that are nearest to the slave elements
    KDTree kd_tree(master_points, _mesh.getMaxLeafSize());
    for (std::size_t i = 0; i < slave_points.size(); i++)
    {
      unsigned int patch_size = 1;
      std::vector<std::size_t> return_index(patch_size);
      kd_tree.neighborSearch(slave_points[i], patch_size, return_index);

      nearest_elem_ids.insert(
          std::pair<dof_id_type, dof_id_type>(slave_elem_ids[i], master_elem_ids[return_index[0]]));
      nearest_elem_ids.insert(
          std::pair<dof_id_type, dof_id_type>(master_elem_ids[return_index[0]], slave_elem_ids[i]));
    }

    // Go over all elements in the flow channel. Take the center of each element and project it onto
    // the heat structure side. Then check that the projected location on the heat structure matches
    // the location of the original center of the flow channel element
    const std::vector<unsigned int> & fch_elem_ids = flow_channel.getElementIDs();
    for (const auto & elem_id : fch_elem_ids)
    {
      const Elem * elem = _mesh.elemPtr(elem_id);
      Point center_pt = elem->centroid();

      const dof_id_type & hs_elem_id = nearest_elem_ids.at(elem_id);
      const unsigned int & hs_elem_side = nearest_elem_side.at(hs_elem_id);
      const Elem * neighbor = _mesh.elemPtr(hs_elem_id);
      const Elem * neighbor_side_elem = neighbor->build_side_ptr(hs_elem_side).release();
      unsigned int neighbor_dim = neighbor_side_elem->dim();
      Point ref_pt =
          FEInterface::inverse_map(neighbor_dim, FEType(), neighbor_side_elem, center_pt);
      Point hs_pt = FEInterface::map(neighbor_dim, FEType(), neighbor_side_elem, ref_pt);
      delete neighbor_side_elem;

      if (!center_pt.absolute_fuzzy_equals(hs_pt))
      {
        logError("The centers of the elements of flow channel '",
                 _flow_channel_name,
                 "' do not equal the centers of the specified heat structure side.");
        break;
      }
    }
  }
}

void
HeatTransferFromHeatStructure1Phase::check() const
{
  HeatTransferFromTemperature1Phase::check();

  checkComponentOfTypeExistsByName<HeatStructure>(_hs_name);

  if (hasComponentByName<HeatStructure>(_hs_name))
  {
    const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
    if (hs.getDimension() == 1)
      logError("1D heat structures cannot be used; 2D heat structures must be used instead.");

    const Real & P_hs = hs.getUnitPerimeter(_hs_side);
    if (MooseUtils::absoluteFuzzyEqual(P_hs, 0.))
      logError("'hs_side' parameter is set to '",
               _hs_side,
               "', but this side of the heat structure '",
               _hs_name,
               "' has radius of zero.");
  }

  if (hasComponentByName<HeatStructure>(_hs_name) &&
      hasComponentByName<FlowChannel1Phase>(_flow_channel_name))
  {
    const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
    const FlowChannel1Phase & flow_channel =
        getComponentByName<FlowChannel1Phase>(_flow_channel_name);

    if (hs.getNumElems() != flow_channel.getNumElems())
      logError("The number of elements in component '",
               _flow_channel_name,
               "' is ",
               flow_channel.getNumElems(),
               ", but the number of axial elements in component '",
               _hs_name,
               "' is ",
               hs.getNumElems(),
               ". They must be the same.");

    if (hs.getLength() != flow_channel.getLength())
      logError("The length of component '",
               _flow_channel_name,
               "' is ",
               flow_channel.getLength(),
               ", but the length of component '",
               _hs_name,
               "' is ",
               hs.getLength(),
               ". They must be the same.");

    checkFlowChannelAlignment();
  }
}

void
HeatTransferFromHeatStructure1Phase::addVariables()
{
  HeatTransferFromTemperature1Phase::addVariables();

  // wall temperature initial condition
  if (!_app.isRestarting())
  {
    const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
    _sim.addFunctionIC(_T_wall_name, hs.getInitialT(), _flow_channel_name);
  }
}

void
HeatTransferFromHeatStructure1Phase::addMooseObjects()
{
  HeatTransferFromTemperature1Phase::addMooseObjects();

  ExecFlagEnum execute_on(MooseUtils::getDefaultExecFlagEnum());
  execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};

  const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);
  const FlowChannel1Phase & flow_channel =
      getComponentByName<FlowChannel1Phase>(_flow_channel_name);

  const UserObjectName heat_flux_uo_name = genName(name(), "heat_flux_uo");
  {
    const std::string class_name = "HeatFluxFromHeatStructure3EqnUserObject";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<std::vector<SubdomainName>>("block") = flow_channel.getSubdomainNames();
    params.set<std::vector<BoundaryName>>("slave_boundary") = {getSlaveSideName()};
    params.set<BoundaryName>("master_boundary") = getMasterSideName();
    params.set<std::vector<VariableName>>("T_wall") = {_T_wall_name};
    params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
    params.set<MaterialPropertyName>("Hw") = _Hw_1phase_name;
    params.set<MaterialPropertyName>("T") = FlowModelSinglePhase::TEMPERATURE;
    params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
    params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
    params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
    params.set<ExecFlagEnum>("execute_on") = execute_on;
    _sim.addUserObject(class_name, heat_flux_uo_name, params);
  }

  {
    const std::string class_name = "OneD3EqnEnergyHeatFlux";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<std::vector<SubdomainName>>("block") = flow_channel.getSubdomainNames();
    params.set<NonlinearVariableName>("variable") = FlowModelSinglePhase::RHOEA;
    params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
    params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
    params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
    params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
    params.set<UserObjectName>("q_uo") = heat_flux_uo_name;
    _sim.addKernel(class_name, genName(name(), "heat_flux_kernel"), params);
  }

  {
    const std::string class_name = "HeatFlux3EqnBC";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<std::vector<BoundaryName>>("boundary") = {getMasterSideName()};
    params.set<NonlinearVariableName>("variable") = HeatConductionModel::TEMPERATURE;
    params.set<UserObjectName>("q_uo") = heat_flux_uo_name;
    params.set<Real>("P_hs_unit") = hs.getUnitPerimeter(_hs_side);
    params.set<unsigned int>("n_unit") = hs.getNumberOfUnits();
    params.set<bool>("hs_coord_system_is_cylindrical") = hs.isCylindrical();
    params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
    params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
    params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
    params.set<std::vector<VariableName>>("T_wall") = {HeatConductionModel::TEMPERATURE};
    _sim.addBoundaryCondition(class_name, genName(name(), "heat_flux_bc"), params);
  }

  // Transfer the temperature of the solid onto the flow channel
  {
    std::string class_name = "VariableValueTransferAux";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<AuxVariableName>("variable") = _T_wall_name;
    params.set<std::vector<BoundaryName>>("boundary") = {getSlaveSideName()};
    params.set<BoundaryName>("paired_boundary") = getMasterSideName();
    params.set<std::vector<VariableName>>("paired_variable") =
        std::vector<VariableName>(1, HeatConductionModel::TEMPERATURE);
    _sim.addAuxBoundaryCondition(class_name, genName(name(), "T_wall_transfer"), params);
  }
}

const BoundaryName &
HeatTransferFromHeatStructure1Phase::getMasterSideName() const
{
  const HeatStructure & hs = getComponentByName<HeatStructure>(_hs_name);

  switch (_hs_side)
  {
    case 0:
      if (hs.getTopBoundaryNames().size() > 0)
        return hs.getTopBoundaryNames()[0];
      else
        return THMMesh::INVALID_BOUNDARY_ID;

    case 1:
      if (hs.getBottomBoundaryNames().size() > 0)
        return hs.getBottomBoundaryNames()[0];
      else
        return THMMesh::INVALID_BOUNDARY_ID;

    default:
      mooseError(name(), ": Unknown side specified in the 'hs_side' parameter.");
  }
}

const BoundaryName &
HeatTransferFromHeatStructure1Phase::getSlaveSideName() const
{
  const FlowChannel1Phase & flow_channel =
      getComponentByName<FlowChannel1Phase>(_flow_channel_name);
  return flow_channel.getNodesetName();
}
<|endoftext|>


<commit_before>#include "inverseIndexStorageUnorderedMap.h"
#ifdef OPENMP
#include <omp.h>
#endif

InverseIndexStorageUnorderedMap::InverseIndexStorageUnorderedMap(size_t pSizeOfInverseIndex, size_t pMaxBinSize) {
	mSignatureStorage = new vector__umapVector(pSizeOfInverseIndex);
	mMaxBinSize = pMaxBinSize;
	mKeys = new vvsize_t(pSizeOfInverseIndex, vsize_t());
	mValues = new vvsize_t(pSizeOfInverseIndex, vsize_t());
}
InverseIndexStorageUnorderedMap::~InverseIndexStorageUnorderedMap() {
	delete mSignatureStorage;
    delete mKeys;
    delete mValues;
}
size_t InverseIndexStorageUnorderedMap::size() const {
	return mSignatureStorage->size();
}
const vsize_t* InverseIndexStorageUnorderedMap::getElement(size_t pVectorId, size_t pHashValue) {
    // std::cout << __LINE__ << std::endl;

	auto iterator = (*mSignatureStorage)[pVectorId].find(pHashValue);
	if (iterator != (*mSignatureStorage)[pVectorId].end()) {
		return &(iterator->second);
	}
    // vsize_t foo;
	return NULL;
    // std::cout << __LINE__ << std::endl;

}
void InverseIndexStorageUnorderedMap::insert(size_t pVectorId, size_t pHashValue, size_t pInstance) {
    // std::cout << __LINE__ << std::endl;

#ifdef OPENMP
#pragma omp critical
#endif
    {
        auto itHashValue_InstanceVector = (*mSignatureStorage)[pVectorId].find(pHashValue);
        // if for hash function h_i() the given hash values is already stored
        if (itHashValue_InstanceVector != (*mSignatureStorage)[pVectorId].end()) {
            // insert the instance id if not too many collisions (maxBinSize)
            if (itHashValue_InstanceVector->second.size() && itHashValue_InstanceVector->second.size() < mMaxBinSize) {
                // insert only if there wasn't any collisions in the past
                if (itHashValue_InstanceVector->second.size() > 0) {
                    itHashValue_InstanceVector->second.push_back(pInstance);
                }
            } else {
                // too many collisions: delete stored ids. empty vector is interpreted as an error code
                // for too many collisions
                itHashValue_InstanceVector->second.clear();
            }
        } else {
            // given hash value for the specific hash function was not avaible: insert new hash value
            vsize_t instanceIdVector;
            instanceIdVector.push_back(pInstance);
            (*mSignatureStorage)[pVectorId][pHashValue] = instanceIdVector;
        }
    }
}

distributionInverseIndex* InverseIndexStorageUnorderedMap::getDistribution() {
    distributionInverseIndex* retVal = new distributionInverseIndex();
    std::map<size_t, size_t> distribution;
    vsize_t numberOfCreatedHashValuesPerHashFunction;
    vsize_t averageNumberOfValuesPerHashValue;
    vsize_t standardDeviationPerNumberOfValuesPerHashValue;
    size_t meanForNumberHashValues = 0;

    for (auto it = mSignatureStorage->begin(); it != mSignatureStorage->end(); ++it) {
        numberOfCreatedHashValuesPerHashFunction.push_back(it->size());
        meanForNumberHashValues += it->size();
        size_t mean = 0;

        for (auto itMap = it->begin(); itMap != it->end(); ++itMap) {
            distribution[itMap->second.size()] += 1;
            mean += itMap->second.size();
        }
        if (it->size() != 0 || mean != 0) {
            mean = mean / it->size();
        }
        averageNumberOfValuesPerHashValue.push_back(mean);

        size_t variance = 0;
        for (auto itMap = it->begin(); itMap != it->end(); ++itMap) {
            variance += pow(static_cast<int>(itMap->second.size()) - mean, 2);
        }

        variance = variance / mSignatureStorage->size();
        int standardDeviation = sqrt(variance);
        standardDeviationPerNumberOfValuesPerHashValue.push_back(standardDeviation);
    }

    size_t varianceForNumberOfHashValues = 0;
    for (auto it = mSignatureStorage->begin(); it != mSignatureStorage->end(); ++it) {
       varianceForNumberOfHashValues += pow(it->size() - meanForNumberHashValues, 2);
    }

    retVal->mean = meanForNumberHashValues;
    retVal->standardDeviation = sqrt(varianceForNumberOfHashValues);

    retVal->totalCountForOccurenceOfHashValues = distribution;
    retVal->standardDeviationForNumberOfValuesPerHashValue = standardDeviationPerNumberOfValuesPerHashValue;
    retVal->meanForNumberOfValuesPerHashValue = averageNumberOfValuesPerHashValue;

    retVal->numberOfCreatedHashValuesPerHashFunction = numberOfCreatedHashValuesPerHashFunction;

    return retVal;
}
void InverseIndexStorageUnorderedMap::prune(int pValue) {
    // std::cout << __LINE__ << std::endl;
    for (auto it = mSignatureStorage->begin(); it != mSignatureStorage->end(); ++it) {
        vsize_t elementsToDelete;
        for (auto itMap = it->begin(); itMap != it->end(); ++itMap) {
            if (itMap->second.size() <= pValue) {
                elementsToDelete.push_back(itMap->first);
            }
            // (*distribution)[itMap->second.size()] += 1;
        }
        for (size_t i = 0; i < elementsToDelete.size(); ++i) {
            it->erase(elementsToDelete[i]);
        }
        elementsToDelete.clear();
    }
    // std::cout << __LINE__ << std::endl;

}

// if pRemoveHashFunctionWithLessEntriesAs == 0 remove every hash function
// which has less entries than mean+standard deviation
// else: remove every hash function which has less entries than pRemoveHashFunctionWithLessEntriesAs
void InverseIndexStorageUnorderedMap::removeHashFunctionWithLessEntriesAs(int pRemoveHashFunctionWithLessEntriesAs) {
    // std::cout << __LINE__ << std::endl;

    if (pRemoveHashFunctionWithLessEntriesAs == 0) {
        int mean = 0;
        int variance = 0;
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            mean += (*mSignatureStorage)[i].size();
        }
        mean = mean / mSignatureStorage->size();
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            variance += pow(static_cast<int>((*mSignatureStorage)[i].size()) - mean, 2);
        }
        variance = variance / mSignatureStorage->size();
        int standardDeviation = sqrt(variance);
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            if ((*mSignatureStorage)[i].size() < mean + standardDeviation) {
                    (*mSignatureStorage)[i].clear();
            }
        }
    } else {
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            if ((*mSignatureStorage)[i].size() < pRemoveHashFunctionWithLessEntriesAs) {
                (*mSignatureStorage)[i].clear();
            }
        }
    }
    // std::cout << __LINE__ << std::endl;

}<commit_msg>extended to not store values with two 00 at the end<commit_after>#include "inverseIndexStorageUnorderedMap.h"
#ifdef OPENMP
#include <omp.h>
#endif

InverseIndexStorageUnorderedMap::InverseIndexStorageUnorderedMap(size_t pSizeOfInverseIndex, size_t pMaxBinSize) {
	mSignatureStorage = new vector__umapVector(pSizeOfInverseIndex);
	mMaxBinSize = pMaxBinSize;
	mKeys = new vvsize_t(pSizeOfInverseIndex, vsize_t());
	mValues = new vvsize_t(pSizeOfInverseIndex, vsize_t());
}
InverseIndexStorageUnorderedMap::~InverseIndexStorageUnorderedMap() {
	delete mSignatureStorage;
    delete mKeys;
    delete mValues;
}
size_t InverseIndexStorageUnorderedMap::size() const {
	return mSignatureStorage->size();
}
const vsize_t* InverseIndexStorageUnorderedMap::getElement(size_t pVectorId, size_t pHashValue) {
    // std::cout << __LINE__ << std::endl;

	auto iterator = (*mSignatureStorage)[pVectorId].find(pHashValue);
	if (iterator != (*mSignatureStorage)[pVectorId].end()) {
		return &(iterator->second);
	}
    // vsize_t foo;
	return NULL;
    // std::cout << __LINE__ << std::endl;

}
void InverseIndexStorageUnorderedMap::insert(size_t pVectorId, size_t pHashValue, size_t pInstance) {
    // std::cout << __LINE__ << std::endl;
    size_t insertValue = pHashValue | 0b11111111111111111111111111111100;
    if (insertValue == 0b11111111111111111111111111111100) {
        return;
    }
#ifdef OPENMP
#pragma omp critical
#endif
    {
        auto itHashValue_InstanceVector = (*mSignatureStorage)[pVectorId].find(pHashValue);
        // if for hash function h_i() the given hash values is already stored
        if (itHashValue_InstanceVector != (*mSignatureStorage)[pVectorId].end()) {
            // insert the instance id if not too many collisions (maxBinSize)
            if (itHashValue_InstanceVector->second.size() && itHashValue_InstanceVector->second.size() < mMaxBinSize) {
                // insert only if there wasn't any collisions in the past
                if (itHashValue_InstanceVector->second.size() > 0) {
                    itHashValue_InstanceVector->second.push_back(pInstance);
                }
            } else {
                // too many collisions: delete stored ids. empty vector is interpreted as an error code
                // for too many collisions
                itHashValue_InstanceVector->second.clear();
            }
        } else {
            // given hash value for the specific hash function was not avaible: insert new hash value
            vsize_t instanceIdVector;
            instanceIdVector.push_back(pInstance);
            (*mSignatureStorage)[pVectorId][pHashValue] = instanceIdVector;
        }
    }
}

distributionInverseIndex* InverseIndexStorageUnorderedMap::getDistribution() {
    distributionInverseIndex* retVal = new distributionInverseIndex();
    std::map<size_t, size_t> distribution;
    vsize_t numberOfCreatedHashValuesPerHashFunction;
    vsize_t averageNumberOfValuesPerHashValue;
    vsize_t standardDeviationPerNumberOfValuesPerHashValue;
    size_t meanForNumberHashValues = 0;

    for (auto it = mSignatureStorage->begin(); it != mSignatureStorage->end(); ++it) {
        numberOfCreatedHashValuesPerHashFunction.push_back(it->size());
        meanForNumberHashValues += it->size();
        size_t mean = 0;

        for (auto itMap = it->begin(); itMap != it->end(); ++itMap) {
            distribution[itMap->second.size()] += 1;
            mean += itMap->second.size();
        }
        if (it->size() != 0 || mean != 0) {
            mean = mean / it->size();
        }
        averageNumberOfValuesPerHashValue.push_back(mean);

        size_t variance = 0;
        for (auto itMap = it->begin(); itMap != it->end(); ++itMap) {
            variance += pow(static_cast<int>(itMap->second.size()) - mean, 2);
        }

        variance = variance / mSignatureStorage->size();
        int standardDeviation = sqrt(variance);
        standardDeviationPerNumberOfValuesPerHashValue.push_back(standardDeviation);
    }

    size_t varianceForNumberOfHashValues = 0;
    for (auto it = mSignatureStorage->begin(); it != mSignatureStorage->end(); ++it) {
       varianceForNumberOfHashValues += pow(it->size() - meanForNumberHashValues, 2);
    }

    retVal->mean = meanForNumberHashValues;
    retVal->standardDeviation = sqrt(varianceForNumberOfHashValues);

    retVal->totalCountForOccurenceOfHashValues = distribution;
    retVal->standardDeviationForNumberOfValuesPerHashValue = standardDeviationPerNumberOfValuesPerHashValue;
    retVal->meanForNumberOfValuesPerHashValue = averageNumberOfValuesPerHashValue;

    retVal->numberOfCreatedHashValuesPerHashFunction = numberOfCreatedHashValuesPerHashFunction;

    return retVal;
}
void InverseIndexStorageUnorderedMap::prune(int pValue) {
    // std::cout << __LINE__ << std::endl;
    for (auto it = mSignatureStorage->begin(); it != mSignatureStorage->end(); ++it) {
        vsize_t elementsToDelete;
        for (auto itMap = it->begin(); itMap != it->end(); ++itMap) {
            if (itMap->second.size() <= pValue) {
                elementsToDelete.push_back(itMap->first);
            }
            // (*distribution)[itMap->second.size()] += 1;
        }
        for (size_t i = 0; i < elementsToDelete.size(); ++i) {
            it->erase(elementsToDelete[i]);
        }
        elementsToDelete.clear();
    }
    // std::cout << __LINE__ << std::endl;

}

// if pRemoveHashFunctionWithLessEntriesAs == 0 remove every hash function
// which has less entries than mean+standard deviation
// else: remove every hash function which has less entries than pRemoveHashFunctionWithLessEntriesAs
void InverseIndexStorageUnorderedMap::removeHashFunctionWithLessEntriesAs(int pRemoveHashFunctionWithLessEntriesAs) {
    // std::cout << __LINE__ << std::endl;

    if (pRemoveHashFunctionWithLessEntriesAs == 0) {
        int mean = 0;
        int variance = 0;
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            mean += (*mSignatureStorage)[i].size();
        }
        mean = mean / mSignatureStorage->size();
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            variance += pow(static_cast<int>((*mSignatureStorage)[i].size()) - mean, 2);
        }
        variance = variance / mSignatureStorage->size();
        int standardDeviation = sqrt(variance);
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            if ((*mSignatureStorage)[i].size() < mean + standardDeviation) {
                    (*mSignatureStorage)[i].clear();
            }
        }
    } else {
        for (size_t i = 0; i < mSignatureStorage->size(); ++i) {
            if ((*mSignatureStorage)[i].size() < pRemoveHashFunctionWithLessEntriesAs) {
                (*mSignatureStorage)[i].clear();
            }
        }
    }
    // std::cout << __LINE__ << std::endl;

}<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX600 グループ・8 ビットタイマ（TMR）定義
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/device.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  8 ビットタイマ（TMR）
		@param[in]	base	ベースアドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base>
	struct tmr_t {

		//-----------------------------------------------------------------//
		/*!
			@brie	タイマカウンタ（TCNT）
		*/
		//-----------------------------------------------------------------//
		static rw8_t<base + 0x08> TCNT;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ A（TCORA）
		*/
		//-----------------------------------------------------------------//
		static rw8_t<base + 0x04> TCORA;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ B（TCORB）
		*/
		//-----------------------------------------------------------------//
		static rw8_t<base + 0x06> TCORB;

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマコントロールレジスタ（TCR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tcr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B3, 2>  CCLR;
			bit_rw_t <io_, bitpos::B5>     OVIE;
			bit_rw_t <io_, bitpos::B6>     CMIEA;
			bit_rw_t <io_, bitpos::B7>     CMIEB;
		};
		static tcr_t<base + 0x00> TCR;

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマカウンタコントロールレジスタ（TCCR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tccr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 3>  CKS;
			bits_rw_t<io_, bitpos::B3, 2>  CSS;
			bit_rw_t <io_, bitpos::B7>     TMRIS;
		};
		static tccr_t<base + 0x0A> TCCR;

	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  8 ビットタイマ（TMR）偶数版
		@param[in]	base	ベースアドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base>
	struct tmr0246_t : public tmr_t<base> {

		//-----------------------------------------------------------------//
		/*!
			@brie	タイマカウンタ（TCNTW）
		*/
		//-----------------------------------------------------------------//
		static rw16_t<base + 0x08> TCNT16;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ A（TCORA）
		*/
		//-----------------------------------------------------------------//
		static rw16_t<base + 0x04> TCORA16;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ B（TCORB）
		*/
		//-----------------------------------------------------------------//
		static rw16_t<base + 0x06> TCORB16;

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマコントロール／ステータスレジスタ（TCSR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tcsr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 2>  OSA;
			bits_rw_t<io_, bitpos::B2, 2>  OSB;
			bit_rw_t <io_, bitpos::B4>     ADTE;
		};
		static tcsr_t<base + 0x02> TCSR;

	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  8 ビットタイマ（TMR）奇数版
		@param[in]	base	ベースアドレス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base>
	struct tmr1357_t : public tmr_t<base> {

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマコントロール／ステータスレジスタ（TCSR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tcsr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 2>  OSA;
			bits_rw_t<io_, bitpos::B2, 2>  OSB;
		};
		static tcsr_t<base + 0x02> TCSR;

	};

	typedef tmr0246_t<0x00088200> TMR0;
	typedef tmr1357_t<0x00088201> TMR1;
	typedef tmr0246_t<0x00088210> TMR2;
	typedef tmr1357_t<0x00088211> TMR3;
#if defined(SIG_RX24T) || defined(SIG_RX66T)
	typedef tmr0246_t<0x00088220> TMR4;
	typedef tmr1357_t<0x00088221> TMR5;
	typedef tmr0246_t<0x00088230> TMR6;
	typedef tmr1357_t<0x00088231> TMR7;
#endif
}
<commit_msg>Update: The reality of the template when it is not optimized<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX600 グループ・8 ビットタイマ（TMR）定義
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/device.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  8 ビットタイマ（TMR）
		@param[in]	base	ベースアドレス
		@param[in]	per		ペリフェラル型
		@param[in]	INT		割り込み型
		@param[in]	cmia	CMIA 型割り込みベクター
		@param[in]	cmib	CMIB 型割り込みベクター
		@param[in]	ovi		OVI 型割り込みベクター
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
	struct tmr_t {

		static const auto PERIPHERAL = per;		///< ペリフェラル型
		static const auto CMIA_VEC = cmia;		///< CMIA 割り込みベクタ
		static const auto CMIB_VEC = cmib;		///< CMIB 割り込みベクタ
		static const auto OVI_VEC  = ovi;		///< OVI 割り込みベクタ
		static const uint32_t PCLK = F_PCLKB;	///< PCLK 周波数

		//-----------------------------------------------------------------//
		/*!
			@brie	タイマカウンタ（TCNT）
		*/
		//-----------------------------------------------------------------//
		typedef rw8_t<base + 0x08> TCNT_;
		static  TCNT_ TCNT;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ A（TCORA）
		*/
		//-----------------------------------------------------------------//
		typedef rw8_t<base + 0x04> TCORA_;
		static  TCORA_ TCORA;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ B（TCORB）
		*/
		//-----------------------------------------------------------------//
		typedef rw8_t<base + 0x06> TCORB_;
		static  TCORB_ TCORB;

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマコントロールレジスタ（TCR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tcr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B3, 2>  CCLR;
			bit_rw_t <io_, bitpos::B5>     OVIE;
			bit_rw_t <io_, bitpos::B6>     CMIEA;
			bit_rw_t <io_, bitpos::B7>     CMIEB;
		};
		typedef tcr_t<base + 0x00> TCR_;
		static  TCR_ TCR;

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマカウンタコントロールレジスタ（TCCR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tccr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 3>  CKS;
			bits_rw_t<io_, bitpos::B3, 2>  CSS;
			bit_rw_t <io_, bitpos::B7>     TMRIS;
		};
		typedef tccr_t<base + 0x0A> TCCR_;
		static  TCCR_ TCCR;
	};
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr_t<base, per, INT, cmia, cmib, ovi>::TCNT_ tmr_t<base, per, INT, cmia, cmib, ovi>::TCNT;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr_t<base, per, INT, cmia, cmib, ovi>::TCORA_ tmr_t<base, per, INT, cmia, cmib, ovi>::TCORA;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr_t<base, per, INT, cmia, cmib, ovi>::TCORB_ tmr_t<base, per, INT, cmia, cmib, ovi>::TCORB;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr_t<base, per, INT, cmia, cmib, ovi>::TCR_ tmr_t<base, per, INT, cmia, cmib, ovi>::TCR;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr_t<base, per, INT, cmia, cmib, ovi>::TCCR_ tmr_t<base, per, INT, cmia, cmib, ovi>::TCCR;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  8 ビットタイマ（TMR）偶数版
		@param[in]	base	ベースアドレス
		@param[in]	per		ペリフェラル型
		@param[in]	INT		割り込み型
		@param[in]	cmia	CMIA 型割り込みベクター
		@param[in]	cmib	CMIB 型割り込みベクター
		@param[in]	ovi		OVI 型割り込みベクター
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
	struct tmr0246_t : public tmr_t<base, per, INT, cmia, cmib, ovi> {

		//-----------------------------------------------------------------//
		/*!
			@brie	タイマカウンタ（TCNTW）
		*/
		//-----------------------------------------------------------------//
		typedef rw16_t<base + 0x08> TCNT16_;
		static  TCNT16_ TCNT16;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ A（TCORA）
		*/
		//-----------------------------------------------------------------//
		typedef rw16_t<base + 0x04> TCORA16_;
		static  TCORA16_ TCORA16;

		//-----------------------------------------------------------------//
		/*!
			@brie	タイムコンスタントレジスタ B（TCORB）
		*/
		//-----------------------------------------------------------------//
		typedef rw16_t<base + 0x06> TCORB16_;
		static  TCORB16_ TCORB16;

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマコントロール／ステータスレジスタ（TCSR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tcsr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 2>  OSA;
			bits_rw_t<io_, bitpos::B2, 2>  OSB;
			bit_rw_t <io_, bitpos::B4>     ADTE;
		};
		typedef tcsr_t<base + 0x02> TCSR_;
		static  TCSR_ TCSR;
	};
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCNT16_ tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCNT16;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCORA16_ tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCORA16;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCORB16_ tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCORB16;
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCSR_ tmr0246_t<base, per, INT, cmia, cmib, ovi>::TCSR;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  8 ビットタイマ（TMR）奇数版
		@param[in]	base	ベースアドレス
		@param[in]	per		ペリフェラル型
		@param[in]	INT		割り込み型
		@param[in]	cmia	CMIA 型割り込みベクター
		@param[in]	cmib	CMIB 型割り込みベクター
		@param[in]	ovi		OVI 型割り込みベクター
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
	struct tmr1357_t : public tmr_t<base, per, INT, cmia, cmib, ovi> {

		//-----------------------------------------------------------------//
		/*!
			@brief	タイマコントロール／ステータスレジスタ（TCSR）
			@param[in]	ofs	アドレス
		*/
		//-----------------------------------------------------------------//
		template <uint32_t ofs>
		struct tcsr_t : public rw8_t<ofs> {
			typedef rw8_t<ofs> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 2>  OSA;
			bits_rw_t<io_, bitpos::B2, 2>  OSB;
		};
		typedef tcsr_t<base + 0x02> TCSR_;
		static  TCSR_ TCSR;
	};
	template <uint32_t base, peripheral per, typename INT, INT cmia, INT cmib, INT ovi>
		typename tmr1357_t<base, per, INT, cmia, cmib, ovi>::TCSR_ tmr1357_t<base, per, INT, cmia, cmib, ovi>::TCSR;

#if defined(SIG_RX64M) || defined(SIG_RX71M) || defined(SIG_RX65N) || defined(SIG_RX72M)
	typedef tmr0246_t<0x00088200, peripheral::TMR0, ICU::VECTOR_SELB,
		ICU::VECTOR_SELB::CMIA0, ICU::VECTOR_SELB::CMIB0, ICU::VECTOR_SELB::OVI0> TMR0;
	typedef tmr1357_t<0x00088201, peripheral::TMR1, ICU::VECTOR_SELB,
		ICU::VECTOR_SELB::CMIA1, ICU::VECTOR_SELB::CMIB1, ICU::VECTOR_SELB::OVI1> TMR1;
	typedef tmr0246_t<0x00088210, peripheral::TMR2, ICU::VECTOR_SELB,
		ICU::VECTOR_SELB::CMIA2, ICU::VECTOR_SELB::CMIB2, ICU::VECTOR_SELB::OVI2> TMR2;
	typedef tmr1357_t<0x00088211, peripheral::TMR3, ICU::VECTOR_SELB,
		ICU::VECTOR_SELB::CMIA3, ICU::VECTOR_SELB::CMIB3, ICU::VECTOR_SELB::OVI3> TMR3;
#endif

#if defined(SIG_RX24T) || defined(SIG_RX66T)
	typedef tmr0246_t<0x00088200, peripheral::TMR0, ICU::VECTOR,
		ICU::VECTOR::CMIA0, ICU::VECTOR::CMIB0, ICU::VECTOR::OVI0> TMR0;
	typedef tmr1357_t<0x00088201, peripheral::TMR1, ICU::VECTOR,
		ICU::VECTOR::CMIA1, ICU::VECTOR::CMIB1, ICU::VECTOR::OVI1> TMR1;
	typedef tmr0246_t<0x00088210, peripheral::TMR2, ICU::VECTOR,
		ICU::VECTOR::CMIA2, ICU::VECTOR::CMIB2, ICU::VECTOR::OVI2> TMR2;
	typedef tmr1357_t<0x00088211, peripheral::TMR3, ICU::VECTOR,
		ICU::VECTOR::CMIA3, ICU::VECTOR::CMIB3, ICU::VECTOR::OVI3> TMR3;
	typedef tmr0246_t<0x00088220, peripheral::TMR4, ICU::VECTOR,
		ICU::VECTOR::CMIA4, ICU::VECTOR::CMIB4, ICU::VECTOR::OVI4> TMR4;
	typedef tmr1357_t<0x00088221, peripheral::TMR5, ICU::VECTOR,
		ICU::VECTOR::CMIA5, ICU::VECTOR::CMIB5, ICU::VECTOR::OVI5> TMR5;
	typedef tmr0246_t<0x00088230, peripheral::TMR6, ICU::VECTOR,
		ICU::VECTOR::CMIA6, ICU::VECTOR::CMIB6, ICU::VECTOR::OVI6> TMR6;
	typedef tmr1357_t<0x00088231, peripheral::TMR7, ICU::VECTOR,
		ICU::VECTOR::CMIA7, ICU::VECTOR::CMIB7, ICU::VECTOR::OVI7> TMR7;
#endif
}
<|endoftext|>


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

#include <parameters/param.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/log.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/time.h>
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_command_ack.h>
#include <string.h>

struct FailureUnit {
	char key[16];
	uint8_t value;
};

static constexpr FailureUnit failure_units[] = {
	{ "gyro", vehicle_command_s::FAILURE_UNIT_SENSOR_GYRO},
	{ "accel", vehicle_command_s::FAILURE_UNIT_SENSOR_ACCEL},
	{ "mag", vehicle_command_s::FAILURE_UNIT_SENSOR_MAG},
	{ "baro", vehicle_command_s::FAILURE_UNIT_SENSOR_BARO},
	{ "gps", vehicle_command_s::FAILURE_UNIT_SENSOR_GPS},
	{ "optical_flow", vehicle_command_s::FAILURE_UNIT_SENSOR_OPTICAL_FLOW},
	{ "vio", vehicle_command_s::FAILURE_UNIT_SENSOR_VIO},
	{ "distance_sensor", vehicle_command_s::FAILURE_UNIT_SENSOR_DISTANCE_SENSOR},
	{ "airspeed", vehicle_command_s::FAILURE_UNIT_SENSOR_AIRSPEED},
	{ "battery", vehicle_command_s::FAILURE_UNIT_SYSTEM_BATTERY},
	{ "motor", vehicle_command_s::FAILURE_UNIT_SYSTEM_MOTOR},
	{ "servo", vehicle_command_s::FAILURE_UNIT_SYSTEM_SERVO},
	{ "avoidance", vehicle_command_s::FAILURE_UNIT_SYSTEM_AVOIDANCE},
	{ "rc_signal", vehicle_command_s::FAILURE_UNIT_SYSTEM_RC_SIGNAL},
	{ "mavlink_signal", vehicle_command_s::FAILURE_UNIT_SYSTEM_MAVLINK_SIGNAL},
};

struct FailureType {
	char key[14];
	uint8_t value;
};

static constexpr FailureType failure_types[] = {
	{ "ok", vehicle_command_s::FAILURE_TYPE_OK},
	{ "off", vehicle_command_s::FAILURE_TYPE_OFF},
	{ "stuck", vehicle_command_s::FAILURE_TYPE_STUCK},
	{ "garbage", vehicle_command_s::FAILURE_TYPE_GARBAGE},
	{ "wrong", vehicle_command_s::FAILURE_TYPE_WRONG},
	{ "slow", vehicle_command_s::FAILURE_TYPE_SLOW},
	{ "delayed", vehicle_command_s::FAILURE_TYPE_DELAYED},
	{ "intermittent", vehicle_command_s::FAILURE_TYPE_INTERMITTENT},
};

static void print_usage()
{
	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
### Description
Inject failures into system.

### Implementation
This system command sends a vehicle command over uORB to trigger failure.

### Examples
Test the GPS failsafe by stopping GPS:

failure gps off
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME_SIMPLE("failure", "command");
	PRINT_MODULE_USAGE_COMMAND_DESCR("help", "Show this help text");
	PRINT_MODULE_USAGE_COMMAND_DESCR("gps|...", "Specify component");
	PRINT_MODULE_USAGE_COMMAND_DESCR("ok|off|...", "Specify failure type");

	PX4_INFO_RAW("\nComponents:\n");
	for (const auto &failure_unit : failure_units) {
		PX4_INFO_RAW("- %s\n", failure_unit.key);
	}

	PX4_INFO_RAW("\nFailure types:\n");
	for (const auto &failure_type : failure_types) {
		PX4_INFO_RAW("- %s\n", failure_type.key);
	}
}

int inject_failure(uint8_t unit, uint8_t type)
{
	const hrt_abstime now = hrt_absolute_time();

	uORB::Subscription command_ack_sub{ORB_ID(vehicle_command_ack)};

	uORB::PublicationQueued<vehicle_command_s> command_pub{ORB_ID(vehicle_command)};
	vehicle_command_s command{};
	command.timestamp = now;
	command.command = vehicle_command_s::VEHICLE_CMD_INJECT_FAILURE;
	command.param1 = static_cast<float>(unit);
	command.param2 = static_cast<float>(type);
	command_pub.publish(command);

	vehicle_command_ack_s ack;
	while (hrt_elapsed_time(&now) < 1000000) {
		if (!command_ack_sub.update(&ack)) {
			if (ack.command == command.command) {
				if (ack.result != vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED) {
					PX4_ERR("Result: %d", ack.result);
					return 1;
				} else {
					return 0;
				}
			}
		}
		px4_usleep(10000);
	}
	PX4_ERR("Timeout waiting for ack");
	return 1;
}

extern "C" __EXPORT int failure_main(int argc, char *argv[])
{
	if (argc == 2 && strcmp(argv[1], "help") == 0) {
		print_usage();
		return 0;
	}

	if (argc < 3) {
		PX4_ERR("Not enough arguments.");
		print_usage();
		return 1;
	}

	int32_t param = 0;
	if (PX4_OK != param_get(param_find("SYS_FAILURE_EN"), &param)) {
		PX4_ERR("Could not get param SYS_FAILURE_EN");
		return 1;
	}

	if (param != 1) {
		PX4_ERR("Failure injection disabled by SYS_FAILURE_EN param.");
		return 1;
	}

	const char *requested_failure_unit = argv[1];
	const char *requested_failure_type = argv[2];

	for (const auto &failure_unit : failure_units) {
		if (strncmp(failure_unit.key, requested_failure_unit, sizeof(failure_unit.key)) != 0) {
			continue;
		}

		for (const auto &failure_type : failure_types) {
			if (strncmp(failure_type.key, requested_failure_type, sizeof(failure_type.key)) != 0) {
				continue;
			}

			return inject_failure(failure_unit.value, failure_type.value);
		}

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

#include <parameters/param.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/log.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/time.h>
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_command_ack.h>
#include <string.h>

using namespace time_literals;

struct FailureUnit {
	char key[16];
	uint8_t value;
};

static constexpr FailureUnit failure_units[] = {
	{ "gyro", vehicle_command_s::FAILURE_UNIT_SENSOR_GYRO},
	{ "accel", vehicle_command_s::FAILURE_UNIT_SENSOR_ACCEL},
	{ "mag", vehicle_command_s::FAILURE_UNIT_SENSOR_MAG},
	{ "baro", vehicle_command_s::FAILURE_UNIT_SENSOR_BARO},
	{ "gps", vehicle_command_s::FAILURE_UNIT_SENSOR_GPS},
	{ "optical_flow", vehicle_command_s::FAILURE_UNIT_SENSOR_OPTICAL_FLOW},
	{ "vio", vehicle_command_s::FAILURE_UNIT_SENSOR_VIO},
	{ "distance_sensor", vehicle_command_s::FAILURE_UNIT_SENSOR_DISTANCE_SENSOR},
	{ "airspeed", vehicle_command_s::FAILURE_UNIT_SENSOR_AIRSPEED},
	{ "battery", vehicle_command_s::FAILURE_UNIT_SYSTEM_BATTERY},
	{ "motor", vehicle_command_s::FAILURE_UNIT_SYSTEM_MOTOR},
	{ "servo", vehicle_command_s::FAILURE_UNIT_SYSTEM_SERVO},
	{ "avoidance", vehicle_command_s::FAILURE_UNIT_SYSTEM_AVOIDANCE},
	{ "rc_signal", vehicle_command_s::FAILURE_UNIT_SYSTEM_RC_SIGNAL},
	{ "mavlink_signal", vehicle_command_s::FAILURE_UNIT_SYSTEM_MAVLINK_SIGNAL},
};

struct FailureType {
	char key[14];
	uint8_t value;
};

static constexpr FailureType failure_types[] = {
	{ "ok", vehicle_command_s::FAILURE_TYPE_OK},
	{ "off", vehicle_command_s::FAILURE_TYPE_OFF},
	{ "stuck", vehicle_command_s::FAILURE_TYPE_STUCK},
	{ "garbage", vehicle_command_s::FAILURE_TYPE_GARBAGE},
	{ "wrong", vehicle_command_s::FAILURE_TYPE_WRONG},
	{ "slow", vehicle_command_s::FAILURE_TYPE_SLOW},
	{ "delayed", vehicle_command_s::FAILURE_TYPE_DELAYED},
	{ "intermittent", vehicle_command_s::FAILURE_TYPE_INTERMITTENT},
};

static void print_usage()
{
	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
### Description
Inject failures into system.

### Implementation
This system command sends a vehicle command over uORB to trigger failure.

### Examples
Test the GPS failsafe by stopping GPS:

failure gps off
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME_SIMPLE("failure", "command");
	PRINT_MODULE_USAGE_COMMAND_DESCR("help", "Show this help text");
	PRINT_MODULE_USAGE_COMMAND_DESCR("gps|...", "Specify component");
	PRINT_MODULE_USAGE_COMMAND_DESCR("ok|off|...", "Specify failure type");

	PX4_INFO_RAW("\nComponents:\n");
	for (const auto &failure_unit : failure_units) {
		PX4_INFO_RAW("- %s\n", failure_unit.key);
	}

	PX4_INFO_RAW("\nFailure types:\n");
	for (const auto &failure_type : failure_types) {
		PX4_INFO_RAW("- %s\n", failure_type.key);
	}
}

int inject_failure(uint8_t unit, uint8_t type)
{
	const hrt_abstime now = hrt_absolute_time();

	uORB::Subscription command_ack_sub{ORB_ID(vehicle_command_ack)};

	uORB::PublicationQueued<vehicle_command_s> command_pub{ORB_ID(vehicle_command)};
	vehicle_command_s command{};
	command.timestamp = now;
	command.command = vehicle_command_s::VEHICLE_CMD_INJECT_FAILURE;
	command.param1 = static_cast<float>(unit);
	command.param2 = static_cast<float>(type);
	command_pub.publish(command);

	vehicle_command_ack_s ack;
	while (hrt_elapsed_time(&now) < 1_s) {
		if (command_ack_sub.update(&ack)) {
			if (ack.command == command.command) {
				if (ack.result != vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED) {
					PX4_ERR("Result: %d", ack.result);
					return 1;
				} else {
					return 0;
				}
			}
		}
		px4_usleep(10000);
	}
	PX4_ERR("Timeout waiting for ack");
	return 1;
}

extern "C" __EXPORT int failure_main(int argc, char *argv[])
{
	if (argc == 2 && strcmp(argv[1], "help") == 0) {
		print_usage();
		return 0;
	}

	if (argc < 3) {
		PX4_ERR("Not enough arguments.");
		print_usage();
		return 1;
	}

	int32_t param = 0;
	if (PX4_OK != param_get(param_find("SYS_FAILURE_EN"), &param)) {
		PX4_ERR("Could not get param SYS_FAILURE_EN");
		return 1;
	}

	if (param != 1) {
		PX4_ERR("Failure injection disabled by SYS_FAILURE_EN param.");
		return 1;
	}

	const char *requested_failure_unit = argv[1];
	const char *requested_failure_type = argv[2];

	for (const auto &failure_unit : failure_units) {
		if (strncmp(failure_unit.key, requested_failure_unit, sizeof(failure_unit.key)) != 0) {
			continue;
		}

		for (const auto &failure_type : failure_types) {
			if (strncmp(failure_type.key, requested_failure_type, sizeof(failure_type.key)) != 0) {
				continue;
			}

			return inject_failure(failure_unit.value, failure_type.value);
		}

		PX4_ERR("Failure type '%s' not found", requested_failure_type);
		return 1;
	}
	PX4_ERR("Component '%s' not found", requested_failure_unit);
	return 1;
}
<|endoftext|>


<commit_before>#include <systems/BladeShooterSystem.h>
#include <components/BladeComponent.h>
#include <vector>
#include <components/PhysicsComponent.h>
#include <components/BladeShooterComponent.h>
#include <game-objects/GameObjectTag.h>
#include <components/Texcoords.h>
#include <components/SplitDirectionComponent.h>

class BladeShooterSystem::BladeShooterSystemImpl{

public:
	BladeShooterSystemImpl(b2World& box2dWorld) : m_box2dWorld(&box2dWorld) {}
	~BladeShooterSystemImpl(){}

	std::unique_ptr<b2World> m_box2dWorld;
	sf::Clock m_clock;

	void update(std::vector<anax::Entity>& entities){
		for(anax::Entity bladeShooterEntity : entities){
			sf::Time currentTime = m_clock.getElapsedTime();
			auto& bladeShooterComp = bladeShooterEntity.getComponent<BladeShooterComponent>();
			auto bladeShooterState = bladeShooterComp.bladeShooterState;
			if(bladeShooterState == BladeShooterState::NOT_STARTED){
				bladeShooterComp.lastTimeBladeShot = m_clock.getElapsedTime();
				bladeShooterComp.bladeShooterState = BladeShooterState::SHOOTING;
				createBlade(bladeShooterEntity);
			}else if((currentTime - bladeShooterComp.lastTimeBladeShot).asMilliseconds() >= bladeShooterComp.delayBetweenBladeShots.asMilliseconds()){
				createBlade(bladeShooterEntity);
				bladeShooterComp.lastTimeBladeShot = currentTime;
			}
		}
	}

	void createBlade(anax::Entity& entity){
		auto& bladeShooterComp = entity.getComponent<BladeShooterComponent>();
		auto& physicsComp = entity.getComponent<PhysicsComponent>();
		b2Body* body = physicsComp.physicsBody;
		b2Vec2 startingPosition = body->GetPosition();
		auto& world = entity.getWorld();

		auto bladeEntity = world.createEntity();
		auto& bladeComp = bladeEntity.addComponent<BladeComponent>();
		auto& bladePhysicsComp = bladeEntity.addComponent<PhysicsComponent>();
		auto& texCoordsComp = bladeEntity.addComponent<Texcoords>();
		auto& splitDirectionComp = bladeEntity.addComponent<SplitDirectionComponent>();
		splitDirectionComp.splitDirection = SplitDirection::NONE;

		bladeComp.bladeLinearVelocity = bladeShooterComp.bladeLinerVelocty;
		bladePhysicsComp.physicsBody = createBladeBody(startingPosition, bladeShooterComp.bladeSize);
		bladeEntity.activate();
	}

	b2Body* createBladeBody(b2Vec2 startingPosition, b2Vec2 shapeSize){
		b2BodyDef bd;
		bd.type = b2_dynamicBody;
		bd.position = startingPosition;
		b2PolygonShape shape;
		shape.SetAsBox(shapeSize.x, shapeSize.y);
		b2FixtureDef fd;
		fd.shape = &shape;
		fd.density = 1.0f;
		fd.filter.categoryBits = GameObjectTag::BLADE;
		fd.filter.maskBits =  ~GameObjectTag::BLADE_SHOOTER | ~GameObjectTag::NINJA_SENSE;

		b2Body* bladeBody  = m_box2dWorld->CreateBody(&bd);
		bladeBody->CreateFixture(&fd);
		return bladeBody;
	}

};

BladeShooterSystem::BladeShooterSystem(b2World& box2dWorld) : Base(anax::ComponentFilter().requires<PhysicsComponent,BladeShooterComponent>()), m_impl(new BladeShooterSystemImpl(box2dWorld)) {
}

BladeShooterSystem::~BladeShooterSystem() {
}

void BladeShooterSystem::update(){
	auto entities = getEntities();
	m_impl->update(entities);
}

<commit_msg>Blades are not affected by gravity<commit_after>#include <systems/BladeShooterSystem.h>
#include <components/BladeComponent.h>
#include <vector>
#include <components/PhysicsComponent.h>
#include <components/BladeShooterComponent.h>
#include <game-objects/GameObjectTag.h>
#include <components/Texcoords.h>
#include <components/SplitDirectionComponent.h>

class BladeShooterSystem::BladeShooterSystemImpl{

public:
	BladeShooterSystemImpl(b2World& box2dWorld) : m_box2dWorld(&box2dWorld) {}
	~BladeShooterSystemImpl(){}

	std::unique_ptr<b2World> m_box2dWorld;
	sf::Clock m_clock;

	void update(std::vector<anax::Entity>& entities){
		for(anax::Entity bladeShooterEntity : entities){
			sf::Time currentTime = m_clock.getElapsedTime();
			auto& bladeShooterComp = bladeShooterEntity.getComponent<BladeShooterComponent>();
			auto bladeShooterState = bladeShooterComp.bladeShooterState;
			if(bladeShooterState == BladeShooterState::NOT_STARTED){
				bladeShooterComp.lastTimeBladeShot = m_clock.getElapsedTime();
				bladeShooterComp.bladeShooterState = BladeShooterState::SHOOTING;
				createBlade(bladeShooterEntity);
			}else if((currentTime - bladeShooterComp.lastTimeBladeShot).asMilliseconds() >= bladeShooterComp.delayBetweenBladeShots.asMilliseconds()){
				createBlade(bladeShooterEntity);
				bladeShooterComp.lastTimeBladeShot = currentTime;
			}
		}
	}

	void createBlade(anax::Entity& entity){
		auto& bladeShooterComp = entity.getComponent<BladeShooterComponent>();
		auto& physicsComp = entity.getComponent<PhysicsComponent>();
		b2Body* body = physicsComp.physicsBody;
		b2Vec2 startingPosition = body->GetPosition();
		auto& world = entity.getWorld();

		auto bladeEntity = world.createEntity();
		auto& bladeComp = bladeEntity.addComponent<BladeComponent>();
		auto& bladePhysicsComp = bladeEntity.addComponent<PhysicsComponent>();
		auto& texCoordsComp = bladeEntity.addComponent<Texcoords>();
		auto& splitDirectionComp = bladeEntity.addComponent<SplitDirectionComponent>();
		splitDirectionComp.splitDirection = SplitDirection::NONE;

		bladeComp.bladeLinearVelocity = bladeShooterComp.bladeLinerVelocty;
		bladePhysicsComp.physicsBody = createBladeBody(startingPosition, bladeShooterComp.bladeSize);
		bladeEntity.activate();
	}

	b2Body* createBladeBody(b2Vec2 startingPosition, b2Vec2 shapeSize){
		b2BodyDef bd;
		bd.type = b2_dynamicBody;
		bd.position = startingPosition;
		b2PolygonShape shape;
		shape.SetAsBox(shapeSize.x, shapeSize.y);
		b2FixtureDef fd;
		fd.shape = &shape;
		fd.density = 1.0f;
		fd.filter.categoryBits = GameObjectTag::BLADE;
		fd.filter.maskBits =  ~GameObjectTag::BLADE_SHOOTER | ~GameObjectTag::NINJA_SENSE;

		b2Body* bladeBody  = m_box2dWorld->CreateBody(&bd);
		bladeBody->SetGravityScale(0.0f);
		bladeBody->CreateFixture(&fd);
		return bladeBody;
	}

};

BladeShooterSystem::BladeShooterSystem(b2World& box2dWorld) : Base(anax::ComponentFilter().requires<PhysicsComponent,BladeShooterComponent>()), m_impl(new BladeShooterSystemImpl(box2dWorld)) {
}

BladeShooterSystem::~BladeShooterSystem() {
}

void BladeShooterSystem::update(){
	auto entities = getEntities();
	m_impl->update(entities);
}

<|endoftext|>


<commit_before><commit_msg>Remove unused function<commit_after><|endoftext|>