text:
'use strict';

angular.module('uiCropper').factory('cropAreaRectangle', ['cropArea', function (CropArea) {
    var CropAreaRectangle = function () {
        CropArea.apply(this, arguments);

        this._resizeCtrlBaseRadius = 15;
        this._resizeCtrlNormalRatio = 0.6;
        this._resizeCtrlHoverRatio = 0.70;
        this._iconMoveNormalRatio = 0.9;
        this._iconMoveHoverRatio = 1.2;

        this._resizeCtrlNormalRadius = this._resizeCtrlBaseRadius * this._resizeCtrlNormalRatio;
        this._resizeCtrlHoverRadius = this._resizeCtrlBaseRadius * this._resizeCtrlHoverRatio;

        this._posDragStartX = 0;
        this._posDragStartY = 0;
        this._posResizeStartX = 0;
        this._posResizeStartY = 0;
        this._posResizeStartSize = {
            w: 0,
            h: 0
        };

        this._resizeCtrlIsHover = -1;
        this._areaIsHover = false;
        this._resizeCtrlIsDragging = -1;
        this._areaIsDragging = false;
    };

    CropAreaRectangle.prototype = new CropArea();

    // return a type string
    CropAreaRectangle.prototype.getType = function () {
        return 'rectangle';
    };

    CropAreaRectangle.prototype._calcRectangleCorners = function () {
        var size = this.getSize();
        var se = this.getSouthEastBound();
        return [
            [size.x, size.y], //northwest
            [se.x, size.y], //northeast
            [size.x, se.y], //southwest
            [se.x, se.y] //southeast
        ];
    };

    CropAreaRectangle.prototype._calcRectangleDimensions = function () {
        var size = this.getSize();
        var se = this.getSouthEastBound();
        return {
            left: size.x,
            top: size.y,
            right: se.x,
            bottom: se.y
        };
    };

    CropAreaRectangle.prototype._isCoordWithinArea = function (coord) {
        var rectangleDimensions = this._calcRectangleDimensions();
        return (coord[0] >= rectangleDimensions.left && coord[0] <= rectangleDimensions.right && coord[1] >= rectangleDimensions.top && coord[1] <= rectangleDimensions.bottom);
    };

    CropAreaRectangle.prototype._isCoordWithinResizeCtrl = function (coord) {
        var resizeIconsCenterCoords = this._calcRectangleCorners();
        var res = -1;
        for (var i = 0, len = resizeIconsCenterCoords.length; i < len; i++) {
            var resizeIconCenterCoords = resizeIconsCenterCoords[i];
            if (coord[0] > resizeIconCenterCoords[0] - this._resizeCtrlHoverRadius && coord[0] < resizeIconCenterCoords[0] + this._resizeCtrlHoverRadius &&
                coord[1] > resizeIconCenterCoords[1] - this._resizeCtrlHoverRadius && coord[1] < resizeIconCenterCoords[1] + this._resizeCtrlHoverRadius) {
                res = i;
                break;
            }
        }
        return res;
    };

    CropAreaRectangle.prototype._drawArea = function (ctx, center, size) {
        ctx.rect(size.x, size.y, size.w, size.h);
    };

    CropAreaRectangle.prototype.draw = function () {
        CropArea.prototype.draw.apply(this, arguments);

        var center = this.getCenterPoint();
        // draw move icon
        this._cropCanvas.drawIconMove([center.x, center.y], this._areaIsHover ? this._iconMoveHoverRatio : this._iconMoveNormalRatio);

        // draw resize thumbs
        var resizeIconsCenterCoords = this._calcRectangleCorners();
        for (var i = 0, len = resizeIconsCenterCoords.length; i < len; i++) {
            var resizeIconCenterCoords = resizeIconsCenterCoords[i];
            this._cropCanvas.drawIconResizeBoxBase(resizeIconCenterCoords, this._resizeCtrlBaseRadius, this._resizeCtrlIsHover === i ? this._resizeCtrlHoverRatio : this._resizeCtrlNormalRatio);
        }
    };

    CropAreaRectangle.prototype.setSizeByScale = function(scale, direction) {
        var center = this.getCenterPoint();
        var size = this.getSize();
        var northWestPoint;
        var southEastPoint;

        if (this._aspect) {
            var newWidth = size.w * scale;
            var newHeight = size.h * scale;
            northWestPoint = {
                x: center.x - (newWidth / 2),
                y: center.y - (newHeight / 2)
            };
            southEastPoint = {
                x: center.x + (newWidth / 2),
                y: center.y + (newHeight / 2)
            };
        } else {
            northWestPoint = {
                x: size.x,
                y: size.y
            };
            southEastPoint = {
                x: size.x + size.w,
                y: size.y + size.h
            };
            switch (direction) {
                case 'up':
                case 'down':
                    southEastPoint.y = size.y + (size.h * scale);
                    break;
                case 'left':
                case 'right':
                    southEastPoint.x = size.x + (size.w * scale);
                    break;
            }
        }

        this.setSizeByCorners(northWestPoint, southEastPoint);
        this._events.trigger('area-resize');
    };

    CropAreaRectangle.prototype.processMouseMove = function (mouseCurX, mouseCurY) {
        var cursor = 'default';
        var res = false;

        this._resizeCtrlIsHover = -1;
        this._areaIsHover = false;

        if (this._areaIsDragging) {
            this.setCenterPointOnMove({
                x: mouseCurX - this._posDragStartX,
                y: mouseCurY - this._posDragStartY
            });
            this._areaIsHover = true;
            cursor = 'move';
            res = true;
            this._events.trigger('area-move');
        } else if (this._resizeCtrlIsDragging > -1) {
            var s = this.getSize();
            var se = this.getSouthEastBound();
            var posX = mouseCurX;
            switch (this._resizeCtrlIsDragging) {
                case 0: // Top Left
                    if (this._aspect) {
                        posX = se.x - ((se.y - mouseCurY) * this._aspect);
                    }
                    this.setSizeByCorners({
                        x: posX,
                        y: mouseCurY
                    }, {
                        x: se.x,
                        y: se.y
                    });
                    cursor = 'nwse-resize';
                    break;
                case 1: // Top Right
                    if (this._aspect) {
                        posX = s.x + ((se.y - mouseCurY) * this._aspect);
                    }
                    this.setSizeByCorners({
                        x: s.x,
                        y: mouseCurY
                    }, {
                        x: posX,
                        y: se.y
                    });
                    cursor = 'nesw-resize';
                    break;
                case 2: // Bottom Left
                    if (this._aspect) {
                        posX = se.x - ((mouseCurY - s.y) * this._aspect);
                    }
                    this.setSizeByCorners({
                        x: posX,
                        y: s.y
                    }, {
                        x: se.x,
                        y: mouseCurY
                    });
                    cursor = 'nesw-resize';
                    break;
                case 3: // Bottom Right
                    if (this._aspect) {
                        posX = s.x + ((mouseCurY - s.y) * this._aspect);
                    }
                    this.setSizeByCorners({
                        x: s.x,
                        y: s.y
                    }, {
                        x: posX,
                        y: mouseCurY
                    });
                    cursor = 'nwse-resize';
                    break;
            }

            this._resizeCtrlIsHover = this._resizeCtrlIsDragging;
            res = true;
            this._events.trigger('area-resize');
        } else {
            var hoveredResizeBox = this._isCoordWithinResizeCtrl([mouseCurX, mouseCurY]);
            if (hoveredResizeBox > -1) {
                switch (hoveredResizeBox) {
                    case 0:
                        cursor = 'nwse-resize';
                        break;
                    case 1:
                        cursor = 'nesw-resize';
                        break;
                    case 2:
                        cursor = 'nesw-resize';
                        break;
                    case 3:
                        cursor = 'nwse-resize';
                        break;
                }
                this._areaIsHover = false;
                this._resizeCtrlIsHover = hoveredResizeBox;
                res = true;
            } else if (this._isCoordWithinArea([mouseCurX, mouseCurY])) {
                cursor = 'move';
                this._areaIsHover = true;
                res = true;
            }
        }

        angular.element(this._ctx.canvas).css({
            'cursor': cursor
        });

        return res;
    };

    CropAreaRectangle.prototype.processMouseDown = function (mouseDownX, mouseDownY) {
        var isWithinResizeCtrl = this._isCoordWithinResizeCtrl([mouseDownX, mouseDownY]);
        if (isWithinResizeCtrl > -1) {
            this._areaIsDragging = false;
            this._areaIsHover = false;
            this._resizeCtrlIsDragging = isWithinResizeCtrl;
            this._resizeCtrlIsHover = isWithinResizeCtrl;
            this._posResizeStartX = mouseDownX;
            this._posResizeStartY = mouseDownY;
            this._posResizeStartSize = this._size;
            this._events.trigger('area-resize-start');
        } else if (this._isCoordWithinArea([mouseDownX, mouseDownY])) {
            this._areaIsDragging = true;
            this._areaIsHover = true;
            this._resizeCtrlIsDragging = -1;
            this._resizeCtrlIsHover = -1;
            var center = this.getCenterPoint();
            this._posDragStartX = mouseDownX - center.x;
            this._posDragStartY = mouseDownY - center.y;
            this._events.trigger('area-move-start');
        }
    };

    CropAreaRectangle.prototype.processMouseUp = function (/*mouseUpX, mouseUpY*/) {
        if (this._areaIsDragging) {
            this._areaIsDragging = false;
            this._events.trigger('area-move-end');
        }
        if (this._resizeCtrlIsDragging > -1) {
            this._resizeCtrlIsDragging = -1;
            this._events.trigger('area-resize-end');
        }
        this._areaIsHover = false;
        this._resizeCtrlIsHover = -1;

        this._posDragStartX = 0;
        this._posDragStartY = 0;
    };

    return CropAreaRectangle;
}]);


text:
/* @flow */

"use strict";

var _interopRequireDefault = require("babel-runtime/helpers/interop-require-default")["default"];

var _interopRequireWildcard = require("babel-runtime/helpers/interop-require-wildcard")["default"];

exports.__esModule = true;

var _babelHelperExplodeAssignableExpression = require("babel-helper-explode-assignable-expression");

var _babelHelperExplodeAssignableExpression2 = _interopRequireDefault(_babelHelperExplodeAssignableExpression);

var _babelTypes = require("babel-types");

var t = _interopRequireWildcard(_babelTypes);

exports["default"] = function (opts /*: {
                                      build: Function;
                                      operator: string;
                                    }*/) /*: Object*/ {
  var visitor = {};

  function isAssignment(node) {
    return node.operator === opts.operator + "=";
  }

  function buildAssignment(left, right) {
    return t.assignmentExpression("=", left, right);
  }

  visitor.ExpressionStatement = function (path, file) {
    // hit the `AssignmentExpression` one below
    if (path.isCompletionRecord()) return;

    var expr = path.node.expression;
    if (!isAssignment(expr)) return;

    var nodes = [];
    var exploded = _babelHelperExplodeAssignableExpression2["default"](expr.left, nodes, file, path.scope, true);

    nodes.push(t.expressionStatement(buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right))));

    path.replaceWithMultiple(nodes);
  };

  visitor.AssignmentExpression = function (path, file) {
    var node = path.node;
    var scope = path.scope;

    if (!isAssignment(node)) return;

    var nodes = [];
    var exploded = _babelHelperExplodeAssignableExpression2["default"](node.left, nodes, file, scope);
    nodes.push(buildAssignment(exploded.ref, opts.build(exploded.uid, node.right)));
    path.replaceWithMultiple(nodes);
  };

  visitor.BinaryExpression = function (path) {
    var node = path.node;

    if (node.operator === opts.operator) {
      path.replaceWith(opts.build(node.left, node.right));
    }
  };

  return visitor;
};

module.exports = exports["default"];

redpajama_set_name: RedPajamaGithub


text:
def servers_tests(connection, params = {}, mocks_implemented = true)
  collection_tests(connection.servers, params, mocks_implemented) do

    if !Fog.mocking? || mocks_implemented
      @instance.wait_for { ready? }
      yield if block_given?
    end

  end
end


text:
package com.talis.hbase.rdf.test.graph;

import com.hp.hpl.jena.graph.BulkUpdateHandler;
import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.Reifier;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.graph.test.AbstractTestGraph;
import com.hp.hpl.jena.graph.test.NodeCreateUtils;

public class AbstractTestGraphHBaseRdf extends AbstractTestGraph
{
	public AbstractTestGraphHBaseRdf( String x ) { super( x ) ; }

	// Tests to skip. TODO: These tests fail, need to check and fix.

	// Isomorphism : Reads into two graphs - but we use the same graph each time hence does not work.
	@Override public void testIsomorphismFile() {}

	public void testBulkAddWithReification()
	{
	//	testBulkAddWithReification( true );
	//	testBulkAddWithReification( false );
	}

	public void testBulkAddWithReification( boolean withReifications )
	{
		Graph graphToUpdate = getGraph();
		BulkUpdateHandler bu = graphToUpdate.getBulkUpdateHandler();
		Graph graphToAdd = graphWith( "pigs might fly; dead can dance" );
		Reifier updatedReifier = graphToUpdate.getReifier();
		Reifier addedReifier = graphToAdd.getReifier();
		xSPOyXYZ( addedReifier );
		bu.add( graphToAdd, withReifications );
		assertIsomorphic
		(
				withReifications ? getReificationTriples( addedReifier ) : graphWith( "" ),
						getReificationTriples( updatedReifier )
		);
	}

	protected void xSPOyXYZ( Reifier r )
	{
		xSPO( r );
		r.reifyAs( NodeCreateUtils.create( "y" ), Triple.create( NodeCreateUtils.create( "X" ), NodeCreateUtils.create( "Y" ), NodeCreateUtils.create( "Z" ) ) );
	}

	protected void aABC( Reifier r )
	{ r.reifyAs( NodeCreateUtils.create( "a" ), Triple.create( NodeCreateUtils.create( "A" ), NodeCreateUtils.create( "B" ), NodeCreateUtils.create( "C" ) ) ); }

	protected void xSPO( Reifier r )
	{ r.reifyAs( NodeCreateUtils.create( "x" ), Triple.create( NodeCreateUtils.create( "S" ), NodeCreateUtils.create( "P" ), NodeCreateUtils.create( "O" ) ) ); }

}


text:
    <head>
        {{ partial "meta.html" . }}
        {{ if .IsHome }}
        <title>{{ .Site.Title }} </title>
        {{ else }}
        <title>{{ .Title }} · {{ .Site.Title }} </title>
        {{ end }}
        <link rel="canonical" href="{{ .Site.BaseURL }}" />
        {{ if .RSSlink }}
        <link rel="feed" type="application/rss+xml" title="{{ .Site.Title }}" href="{{ .RSSlink }}" />
        <link rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" href="{{ .RSSlink }}" />
        {{ end }}
        <link href="/css/main.css" rel="stylesheet" type="text/css"/>
        <link href="/css/atom-one-light.css" rel="stylesheet" type="text/css"/>
        <link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300|Montserrat:700" rel="stylesheet" type="text/css"/>
        <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" type="text/css"/>
    </head>


text:
using namespace reflectionzeug;
using namespace globjects;
using namespace gloperate;
using namespace gl;

static const char * s_vertexShader = R"(
#version 140
#extension GL_ARB_explicit_attrib_location : require

uniform mat4 modelViewProjectionMatrix;

layout (location = 0) in vec2 a_vertex;
out vec2 v_uv;

void main()
{
    v_uv = a_vertex * 0.5 + 0.5;
    gl_Position = modelViewProjectionMatrix * vec4(a_vertex, 0.0, 1.0);
}
)";

static const char * s_fragmentShader = R"(
#version 140
#extension GL_ARB_explicit_attrib_location : require

uniform sampler2D source;

layout (location = 0) out vec4 fragColor;

in vec2 v_uv;

void main()
{
    fragColor = texture(source, v_uv);
}
)";

MultiFramePainter::MultiFramePainter(ResourceManager & resourceManager, const cpplocate::ModuleInfo & moduleInfo)
: Painter("MultiFramePainter", resourceManager, moduleInfo)
, m_animation(true)
, m_background(0, 0, 0, 255)
, m_textureFilename("")
, m_angle(0.0f)
{
    const auto moep = glkernel::kernel2{ };

    // Get data path
    std::string dataPath = moduleInfo.value("dataPath");
    dataPath = iozeug::FilePath(dataPath).path();
    if (dataPath.size() > 0) dataPath = dataPath + "/";
    else                     dataPath = "data/";

    // Get texture filename
    m_textureFilename = dataPath + "logo/gloperate-logo.png";

    // Setup painter
    m_targetFramebufferCapability = addCapability(new gloperate::TargetFramebufferCapability());
    m_viewportCapability = addCapability(new gloperate::ViewportCapability());
    m_timeCapability = addCapability(new gloperate::VirtualTimeCapability());

    m_timeCapability->setLoopDuration(2.0f * glm::pi<float>());

    // Register properties
    addProperty<bool>("Animation", this, &MultiFramePainter::animation, &MultiFramePainter::setAnimation);
    addProperty<Color>("BackgroundColor", this, &MultiFramePainter::background, &MultiFramePainter::setBackground);
    addProperty<FilePath>("Texture", this, &MultiFramePainter::texture, &MultiFramePainter::setTexture);
}

MultiFramePainter::~MultiFramePainter()
{
}

bool MultiFramePainter::animation() const
{
    return m_animation;
}

void MultiFramePainter::setAnimation(const bool & enabled)
{
    m_animation = enabled;

    m_timeCapability->setEnabled(m_animation);
}

Color MultiFramePainter::background() const
{
    return m_background;
}

void MultiFramePainter::setBackground(const Color & color)
{
    m_background = color;
}

FilePath MultiFramePainter::texture() const
{
    return m_textureFilename;
}

void MultiFramePainter::setTexture(const FilePath & filename)
{
    m_textureFilename = filename;

    m_texture = nullptr;
}

void MultiFramePainter::onInitialize()
{
#ifdef __APPLE__
    Shader::clearGlobalReplacements();
    Shader::globalReplace("#version 140", "#version 150");

    debug() << "Using global OS X shader replacement '#version 140' -> '#version 150'" << std::endl;
#endif

    createAndSetupCamera();
    createAndSetupTexture();
    createAndSetupGeometry();
}

void MultiFramePainter::onPaint()
{
    if (m_viewportCapability->hasChanged())
    {
        glViewport(m_viewportCapability->x(), m_viewportCapability->y(), m_viewportCapability->width(), m_viewportCapability->height());

        m_viewportCapability->setChanged(false);
    }

    globjects::Framebuffer * fbo = m_targetFramebufferCapability->framebuffer();

    if (!fbo)
    {
        fbo = globjects::Framebuffer::defaultFBO();
    }

    fbo->bind(GL_FRAMEBUFFER);

    // [TODO] Add onIdle()/onUpdate() callback and implement framerate independent animation
    m_angle = m_timeCapability->time();

    gl::glClearColor(
        (float)m_background.red()   / 255.0f,
        (float)m_background.green() / 255.0f,
        (float)m_background.blue()  / 255.0f,
        1.0f);
    gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT);

    glm::mat4 model = glm::mat4(1.0);
    model = glm::rotate(model, m_angle, glm::vec3(0.0, 1.0, 0.0));

    m_program->setUniform("viewProjectionMatrix",      m_camera->viewProjection());
    m_program->setUniform("modelViewProjectionMatrix", m_camera->viewProjection() * model);

    if (!m_texture) {
        createAndSetupTexture();
    }

    if (m_texture) {
        gl::glActiveTexture(gl::GL_TEXTURE0 + 0);
        m_texture->bind();
    }

    m_program->use();
    m_vao->drawArrays(gl::GL_TRIANGLE_STRIP, 0, 4);
    m_program->release();

    if (m_texture) {
        m_texture->unbind();
    }

    globjects::Framebuffer::unbind(GL_FRAMEBUFFER);
}

void MultiFramePainter::createAndSetupCamera()
{
    m_camera = new Camera();
    m_camera->setEye(glm::vec3(0.0, 0.0, 12.0));
}

void MultiFramePainter::createAndSetupTexture()
{
    // Try to load texture
    m_texture = m_resourceManager.load<globjects::Texture>(m_textureFilename.toString());

    // Check if texture is valid
    if (!m_texture) {
        // Create procedural texture
        static const int w(256);
        static const int h(256);
        unsigned char data[w * h * 4];

        std::random_device rd;
        std::mt19937 generator(rd());
        std::poisson_distribution<> r(0.2);

        for (int i = 0; i < w * h * 4; ++i) {
            data[i] = static_cast<unsigned char>(255 - static_cast<unsigned char>(r(generator) * 255));
        }

        m_texture = globjects::Texture::createDefault(gl::GL_TEXTURE_2D);
        m_texture->image2D(0, gl::GL_RGBA8, w, h, 0, gl::GL_RGBA, gl::GL_UNSIGNED_BYTE, data);
    }
}

void MultiFramePainter::createAndSetupGeometry()
{
    static const std::array<glm::vec2, 4> raw {
        glm::vec2( +1.f, -1.f ),
        glm::vec2( +1.f, +1.f ),
        glm::vec2( -1.f, -1.f ),
        glm::vec2( -1.f, +1.f ) };

    m_vao = new VertexArray;
    m_buffer = new Buffer();
    m_buffer->setData(raw, gl::GL_STATIC_DRAW);

    auto binding = m_vao->binding(0);
    binding->setAttribute(0);
    binding->setBuffer(m_buffer, 0, sizeof(glm::vec2));
    binding->setFormat(2, gl::GL_FLOAT, gl::GL_FALSE, 0);
    m_vao->enable(0);

    StringTemplate * vertexShaderSource   = new StringTemplate(new StaticStringSource(s_vertexShader  ));
    StringTemplate * fragmentShaderSource = new StringTemplate(new StaticStringSource(s_fragmentShader));

#ifdef __APPLE__
    vertexShaderSource  ->replace("#version 140", "#version 150");
    fragmentShaderSource->replace("#version 140", "#version 150");
#endif

    m_vertexShader   = new Shader(gl::GL_VERTEX_SHADER,   vertexShaderSource);
    m_fragmentShader = new Shader(gl::GL_FRAGMENT_SHADER, fragmentShaderSource);
    m_program = new Program();
    m_program->attach(m_vertexShader, m_fragmentShader);

    m_program->setUniform("source", 0);
}


text:
<?php

function customizer_css() {
    ?>

    <?php
}
add_action('wp_head', 'customizer_css');

/*
*ajax点赞
*/
add_action('wp_ajax_nopriv_specs_zan', 'specs_zan');
add_action('wp_ajax_specs_zan', 'specs_zan');
function specs_zan(){
    global $wpdb,$post;
    $id = $_POST["um_id"];
    $action = $_POST["um_action"];
    if ( $action == 'ding'){
        $specs_raters = get_post_meta($id,'specs_zan',true);
        $expire = time() + 99999999;
        $domain = ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false; // make cookies work with localhost
        setcookie('specs_zan_'.$id,$id,$expire,'/',$domain,false);
        if (!$specs_raters || !is_numeric($specs_raters)) {
            update_post_meta($id, 'specs_zan', 1);
        }
        else {
            update_post_meta($id, 'specs_zan', ($specs_raters + 1));
        }
        echo get_post_meta($id,'specs_zan',true);
    }
    die;
}

function get_the_link_items($id = null){
    $bookmarks = get_bookmarks('orderby=date&category=' .$id );
    $output = '';
    if ( !empty($bookmarks) ) {
        $output .= '
';
        foreach ($bookmarks as $bookmark) {
            $output .=  '
link_url . '" title="' . $bookmark->link_description . '" target="_blank" >'. $bookmark->link_name .'
'. $bookmark->link_description .'

';
        }
        $output .= '
';
    }
    return $output;
}

function get_link_items(){
    $linkcats = get_terms( 'link_category' );
    if ( !empty($linkcats) ) {
        foreach( $linkcats as $linkcat){
            $result .=  '
'.$linkcat->name.'
';
            if( $linkcat->description ) $result .= '
' . $linkcat->description . '
';
            $result .=  get_the_link_items($linkcat->term_id);
        }
    } else {
        $result = get_the_link_items();
    }
    return $result;
}

function shortcode_link(){
    return get_link_items();
}
add_shortcode('bigfalink', 'shortcode_link');

//图片七牛云缓存
add_filter( 'upload_dir', 'wpjam_custom_upload_dir' );
function wpjam_custom_upload_dir( $uploads ) {
	$upload_path = '';
	$upload_url_path = akina_option('qiniu_cdn');

	if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) {
		$uploads['basedir']  = WP_CONTENT_DIR . '/uploads';
	} elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
		$uploads['basedir'] = path_join( ABSPATH, $upload_path );
	} else {
		$uploads['basedir'] = $upload_path;
	}

	$uploads['path'] = $uploads['basedir'].$uploads['subdir'];

	if ( $upload_url_path ) {
		$uploads['baseurl'] = $upload_url_path;
		$uploads['url'] = $uploads['baseurl'].$uploads['subdir'];
	}
	return $uploads;
}

//删除自带小工具
function unregister_default_widgets() {
unregister_widget("WP_Widget_Pages");
unregister_widget("WP_Widget_Calendar");
unregister_widget("WP_Widget_Archives");
unregister_widget("WP_Widget_Links");
unregister_widget("WP_Widget_Meta");
unregister_widget("WP_Widget_Search");
unregister_widget("WP_Widget_Text");
unregister_widget("WP_Widget_Categories");
unregister_widget("WP_Widget_Recent_Posts");
unregister_widget("WP_Widget_Recent_Comments");
unregister_widget("WP_Widget_RSS");
unregister_widget("WP_Widget_Tag_Cloud");
unregister_widget("WP_Nav_Menu_Widget");
}
add_action("widgets_init", "unregister_default_widgets", 11);


text:
require 'rails_helper'
describe "Updating Papers", :type => :feature do
  before(:each) do
    @paper = FactoryGirl.create(:paper)
  end

  it "should update the text and add an additional author on the overview page" do
    new_author = FactoryGirl.create(:author, :first_name => "Hasso", :last_name => "Plattner")
    visit paper_path(@paper)
    click_on("Edit")
    new_year = @paper.year + 10
    fill_in "paper_year", :with => new_year
    last_author_index = @paper.authors.count + 1
    select(new_author.name, :from => "paper_author_id_#{last_author_index}")
    submit_form
    expect(current_path).to eq(paper_path(@paper))
    expect(page).to have_text(new_year)
    expect(page).to have_text(new_author.name)
    expect(page).to have_text(@paper.authors.first.name)
    expect(last_author_index).to eq(@paper.authors.count)
  end

  it "should replace an author" do
    old_author = @paper.authors.first
    new_author = FactoryGirl.create(:author, :first_name => "Hasso", :last_name => "Plattner")
    visit edit_paper_path(@paper)
    select(new_author.name, :from => "paper_author_id_1")
    submit_form()
    expect(page).to have_text(new_author.name)
    expect(page).to_not have_text(old_author.name)
  end

  it "should delete an author" do
    old_author = @paper.authors.first
    visit edit_paper_path(@paper)
    select("(none)", :from => "paper_author_id_1")
    submit_form()
    expect(page).to_not have_text(old_author.name)
  end
end


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _9.User_Logs
{
    class UserLogs
    {
        static void Main(string[] args)
        {
            SortedDictionary<string, Dictionary<string, int>> logsByUser = new SortedDictionary<string, Dictionary<string, int>>();
            string input = Console.ReadLine();

            while (input != "end")
            {
                string[] logInfo = input.Split();

                string[] ipInfo = logInfo[0].Split('=');
                string iP = ipInfo[1];

                string[] userInfo = logInfo[2].Split('=');
                string user = userInfo[1];

                // Make sure that the user is not in the logByUser DS
                if (!logsByUser.ContainsKey(user))
                {
                    logsByUser.Add(user, new Dictionary<string, int>());
                    logsByUser[user].Add(iP, 0); // Initialize IP with value 0, so i can increment the value later like this: logsByUser[user][iP]++
                }
                else if (!logsByUser[user].ContainsKey(iP)) // Possible IP missing, if user is in the logByUser DB
                {
                    logsByUser[user].Add(iP, 0);
                }

                logsByUser[user][iP]++;

                input = Console.ReadLine();
            }

            foreach (var outerPair in logsByUser)
            {
                Console.WriteLine("{0}:", outerPair.Key);
                Console.WriteLine("{0}.", string.Join(", ", outerPair.Value.Select(x => $"{x.Key} => {x.Value}")));
            }
        }
    }
}


text:
package io.fabric8.fab.osgi;

import io.fabric8.fab.osgi.internal.FabConnection;
import io.fabric8.fab.osgi.internal.ServiceProvider;
import org.osgi.service.url.AbstractURLStreamHandlerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

public class FabURLHandler extends AbstractURLStreamHandlerService {

    private static String SYNTAX = "fab: fab-jar-uri";
    private static final Logger logger = LoggerFactory.getLogger(FabURLHandler.class);

    private ServiceProvider serviceProvider;

    private FabResolverFactory fabResolverFactory;

    /**
     * Open the connection for the given URL.
     *
     * @param url the url from which to open a connection.
     * @return a connection on the specified URL.
     * @throws java.io.IOException if an error occurs or if the URL is malformed.
     */
    @Override
	public FabConnection openConnection(URL url) throws IOException {
		if (url.getPath() == null || url.getPath().trim().length() == 0) {
			throw new MalformedURLException("Path can not be null or empty. Syntax: " + SYNTAX );
		}
		URL fabJarURL = new URL(url.getPath());

		logger.debug("FAB jar URL is: [" + fabJarURL + "]");

        return new FabConnection(fabJarURL, fabResolverFactory, serviceProvider);
	}

    public void setFabResolverFactory(FabResolverFactory fabResolverFactory) {
        this.fabResolverFactory = fabResolverFactory;
    }

    public void setServiceProvider(ServiceProvider serviceProvider) {
        this.serviceProvider = serviceProvider;
    }
}


text:
static unsigned base_window[] = {
    [HIT_RAINBOW_300] = 50,  // guess
    [HIT_300]         = 80,
    [HIT_200]         = 110, // guess
    [HIT_100]         = 140,
    [HIT_50]          = 200,
    [HIT_MISS]        = 370, // guess
};

static unsigned step_window[] = {
    [HIT_RAINBOW_300] = 5, // guess
    [HIT_300]         = 6,
    [HIT_200]         = 7, // guess
    [HIT_100]         = 8,
    [HIT_50]          = 10,
    [HIT_MISS]        = 12,
};

char const *hit_str[] = {
    [HIT_RAINBOW_300] = "MAX",
    [HIT_50] = "50",
    [HIT_100] = "100",
    [HIT_200] = "200",
    [HIT_300] = "300",
    [HIT_MISS] = "miss",
};

static double base_hit_window(
    double overall_difficulty, double base_window, double window_step)
{
    return base_window - window_step * overall_difficulty;
}

#define TWO_THIRD  (.666666666666666)
#define FOUR_THIRD (1.33333333333333)

int osux_get_approach_time(double ar, int mods)
{
    double step = 120.0, base = 1800.0;

    if (mods & MOD_EASY)
        ar /= 2;
    else if (mods & MOD_HARDROCK)
        ar = min(10., 1.4 * ar);

    if (likely( ar > 5.0 )) {
        ar -= 5;
        step = 150.0;
        base = 1200.0;
    }

    double time = base - ar * step;
    if (mods & MOD_DOUBLETIME)
        time *= TWO_THIRD;
    else if (mods & MOD_HALFTIME)
        time *= FOUR_THIRD;

    return (int) time;
}

void osux_get_hit_windows(
    double window[], // Array of size MAX_HIT_TYPE to be filled by this function
    double od, // map overall difficulty
    int mods) // game mods, only EZ,HR,,HT,DT(or NC) have influence on hit window
{
    if (mods & MOD_EASY)
        od /= 2.;
    else if (mods & MOD_HARDROCK)
        od = min(10., 1.4 * od);

    memset(window, 0, sizeof window[0] * MAX_HIT_TYPE);

    for (unsigned iHit = 0; iHit < MAX_HIT_TYPE; ++iHit) {
        window[iHit] = base_hit_window(
            od, base_window[iHit], step_window[iHit]);

        if (mods & MOD_DOUBLETIME)
            window[iHit] *= TWO_THIRD;
        else if (mods & MOD_HALFTIME)
            window[iHit] *= FOUR_THIRD;
    }
}

static void print_hit_windows(double window[])
{
    for (unsigned i = 0; i < MAX_HIT_TYPE; ++i)
        printf("hit_window '%s': %g\n", hit_str[i], window[i]);
}

#define HIT_KEY_DIFF(d1, d2)                                    \
    (HIT_KEY_PRESSED((d1)->keys) ^ HIT_KEY_PRESSED((d2)->keys))

static int get_hit_type_std(double window[], int64_t distance)
{
    distance = labs(distance);

    if (distance < window[HIT_300])
        return HIT_300;
    else if (distance < window[HIT_100])
        return HIT_100;
    else if (distance < window[HIT_50])
        return HIT_50;
    else
        return HIT_MISS;
}

static int get_hit_type_taiko(double window[], int64_t distance)
{
    distance = labs(distance);

    if (distance < window[HIT_300])
        return HIT_300;
    else if (distance < window[HIT_50])
        return HIT_100;
    else
        return HIT_MISS;
}

static inline int64_t time_distance(osux_keypress *kp, osux_hitobject *ho)
{
    return (int64_t) kp->offset - ho->offset;
}

static int cmp_time_offset(void const *a, void const *b)
{
    return ((osux_replay_data const *)a)->time_offset -
        ((osux_replay_data const*)b)->time_offset;
}

static void print_time_offset_human_readable(int64_t offset)
{
    int64_t minutes, seconds, milliseconds;
    milliseconds = offset % 1000;
    offset /= 1000;
    seconds = offset % 60;
    minutes = offset / 60;
    printf("%ld: %ldm %lds.%03ld", offset*1000+milliseconds,
           minutes, seconds, milliseconds);
}

// return value's nth set bit, all other bits are zeroed
static uint32_t get_nth_bit_set(uint32_t value, unsigned n)
{
    unsigned shift = 0;
    while (n > 0) {

        if (value & 1)
            n--;
        value >>= 1;
        ++ shift;
    }
    return 1U << (shift-1);
}

static unsigned bit_set_count(uint32_t value)
{
    unsigned count = 0;
    for (unsigned i = 0; i < 32; ++i)
        if ((value >> i) & 1)
            ++ count;
    return count;
}

// remove double keypress in standart difficulties replay
// these double appear because keyboard hit key will also flag as
// mouse hit key (this is the reason why you cant click with mouse when
// your mouse keys are pressed
static void keypress_remove_doubles(osux_hits *h)
{
    if ((h->game_mode != GAME_MODE_STD && h->game_mode != GAME_MODE_TAIKO)
        || !h->keypress_count)
        return;

    osux_keypress *unique_kp;
    size_t unique_kp_size;
    osux_keypress *kp = h->keypress;

    ALLOC_ARRAY(unique_kp, unique_kp_size, h->keypress_count);
    unique_kp_size = 1;
    // copy the first one
    memcpy(&unique_kp[0], &kp[0], sizeof*kp);

    for (unsigned i = 1; i < h->keypress_count; ++i) {
        unsigned or_key = kp[i].key | kp[i-1].key;
        if ((kp[i].offset == kp[i-1].offset) &&
            (kp[i].release == kp[i-1].release) &&
            (or_key == KEY_LEFT || or_key == KEY_RIGHT)) {
            // skip if this is the same keypress
            continue;
        }
        memcpy(&unique_kp[unique_kp_size], &kp[i], sizeof*kp);
        ++ unique_kp_size;
    }

    g_free(h->keypress);
    h->keypress = unique_kp;
    h->keypress_count = unique_kp_size;
}

static int osux_hits_compute_data(
    osux_hits *h, osux_replay_data const *data, size_t data_count)
{
    ALLOC_ARRAY(h->data, h->data_count, data_count-2);
    COPY_ARRAY(h->data+1, data+2, data_count-3); // evict first, second and last
    qsort(h->data+1, h->data_count-1, sizeof*data, &cmp_time_offset);
    memset(h->data, 0, sizeof*data); // zero first element
    return 0;
}

static int osux_hits_compute_keypress(osux_hits *h)
{
    size_t keypress_cap;
    osux_replay_data *data = h->data;
    h->keypress_count = 0;
    ALLOC_ARRAY(h->keypress, keypress_cap, 500);

    for (unsigned i = 1; i < h->data_count; ++i) {
        int keys_diff = HIT_KEY_DIFF(&data[i], &data[i-1]);
        if (keys_diff != 0) {
            unsigned key_count = bit_set_count(keys_diff);
            HANDLE_ARRAY_SIZE(h->keypress,
                              h->keypress_count+key_count,
                              keypress_cap);
            for (unsigned k = 1; k <= key_count; ++k) {

                osux_keypress *kp = &h->keypress[h->keypress_count];
                kp->offset = data[i].time_offset;
                kp->key = get_nth_bit_set(keys_diff, k);
                if (kp->key & data[i].keys)
                    kp->release = false;
                else
                    kp->release = true;
                ++ h->keypress_count;
            }
        }
    }
    keypress_remove_doubles(h);
    return 0;
}

void osux_hits_print_keypress(osux_hits *h)
{
    for (unsigned i = 0; i < h->keypress_count; ++i) {
        osux_keypress *kp = &h->keypress[i];
        print_time_offset_human_readable(kp->offset);
        printf(" | key=%u -- %s\n", kp->key, kp->release ? "RELEASE" : "PRESS");
    }
}

// basic hit computation for standard mode:
// all spinner / slider are free 300's
// only timing is currently taken into account; no position
static int osux_hits_compute_hits_std_basic(
    osux_hits *h, osux_beatmap const *beatmap)
{
    double window[MAX_HIT_TYPE];
    osux_keypress *p_keypress = h->keypress;
    osux_keypress *keypresses_end = h->keypress + h->keypress_count;
    osux_hitobject *p_hitobject;
    osux_hitobject *hitobjects_end = beatmap->hitobjects + beatmap->hitobject_count;
    int i_hitobject;
    int64_t max_distance = 0;

    osux_get_hit_windows(window, h->overall_difficulty, h->mods);
    ALLOC_ARRAY(h->hits, h->hits_size, beatmap->hitobject_count);

    for ( p_hitobject = &beatmap->hitobjects[0], i_hitobject = 0;
          p_hitobject != hitobjects_end;
          ++ p_hitobject, ++ i_hitobject   )
    {
        int64_t distance = time_distance( p_keypress, p_hitobject );
        max_distance = max(max_distance, labs(distance));

        // get first key press in (miss) hit window
        while ((p_keypress != keypresses_end && p_keypress->release)
               || distance < -window[HIT_MISS])
        {
            ++ p_keypress;
            distance = time_distance( p_keypress, p_hitobject );
        }

        // free win spinner
        if (HIT_OBJECT_IS_SPINNER(p_hitobject))
        {
            h->hits[i_hitobject].hit_type = HIT_300;
            h->hits[i_hitobject].hitted = true;

            while (p_keypress != keypresses_end &&
                   p_keypress->offset < p_hitobject->end_offset)
            {
                // get out of spinner
                ++ p_keypress;
            }
            continue;
        }

        // if no keypress in the hit window, that's a miss
        if (distance > window[HIT_50]) {
            h->hits[i_hitobject].hitted = false;
            h->hits[i_hitobject].hit_type = HIT_MISS;

            if (distance < window[HIT_MISS] && HIT_OBJECT_IS_SLIDER(p_hitobject))
            {
                h->hits[i_hitobject].hit_type = HIT_300;
                h->hits[i_hitobject].hitted = true;
                ++ p_keypress;
                continue;
            }
            printf("missed 'after' distance=%ld, hit_offset=%ld, ho_offset=%ld\n",
                   distance, p_keypress->offset, p_hitobject->offset);
        } else {
            h->hits[i_hitobject].hitted = true;
            if (HIT_OBJECT_IS_CIRCLE(p_hitobject))
                h->hits[i_hitobject].hit_type = get_hit_type_std(window, distance);
            else
                // free win slider
                h->hits[i_hitobject].hit_type = HIT_300;

            printf("hit %s distance=%ld, hit_offset=%ld, ho_offset=%ld\n",
                   hit_str[h->hits[i_hitobject].hit_type], distance,
                   p_keypress->offset, p_hitobject->offset);
            ++ p_keypress;
        }
    }

    print_hit_windows(window);
    printf("OD: %g\n", beatmap->OverallDifficulty);
    printf("max_distance: %ld\n", max_distance);
    return 0;
}

// basic hit computation for taiko mode:
// drum roll(slider) is ignored
// shaker (spinner) is free win
static int osux_hits_compute_hits_taiko_basic(
    osux_hits *h, osux_beatmap const *beatmap)
{
    double window[MAX_HIT_TYPE];
    osux_keypress *p_keypress = h->keypress;
    osux_keypress *keypresses_end = h->keypress + h->keypress_count;
    osux_hitobject *p_hitobject;
    osux_hitobject *hitobjects_end = beatmap->hitobjects + beatmap->hitobject_count;
    int i_hitobject;
    int64_t max_distance = 0;

    osux_get_hit_windows(window, h->overall_difficulty, h->mods);
    ALLOC_ARRAY(h->hits, h->hits_size, beatmap->hitobject_count);

    for ( p_hitobject = &beatmap->hitobjects[0], i_hitobject = 0;
          p_hitobject != hitobjects_end;
          ++ p_hitobject, ++ i_hitobject   )
    {
        int64_t distance = time_distance( p_keypress, p_hitobject );

        // get first key press in (miss) hit window
        while ((p_keypress != keypresses_end && p_keypress->release)
               || distance < -window[HIT_50])
        {
            ++ p_keypress;
            distance = time_distance( p_keypress, p_hitobject );
        }

        // free win shaker/spinner
        if (HIT_OBJECT_IS_SPINNER(p_hitobject) || HIT_OBJECT_IS_SLIDER(p_hitobject))
        {
            h->hits[i_hitobject].hit_type = HIT_300;
            h->hits[i_hitobject].hitted = true;

            while (p_keypress != keypresses_end &&
                   p_keypress->offset < p_hitobject->end_offset)
            {
                // get out of shaker/spinner
                ++ p_keypress;
            }
            continue;
        }

        // if no keypress in the hit window, that's a miss
        if (distance > window[HIT_50]) {
            h->hits[i_hitobject].hitted = false;
            h->hits[i_hitobject].hit_type = HIT_MISS;
            printf("hit %s distance=%ld, hit_offset=%ld, ho_offset=%ld\n",
                   hit_str[h->hits[i_hitobject].hit_type], distance,
                   p_keypress->offset, p_hitobject->offset);
        } else {
            h->hits[i_hitobject].hitted = true;
            if (HIT_OBJECT_IS_CIRCLE(p_hitobject)) {
                h->hits[i_hitobject].hit_type =
                    get_hit_type_taiko(window, distance);
            } else
                // free win slider
                h->hits[i_hitobject].hit_type = HIT_300;
            printf("hit %s distance=%ld, hit_offset=%ld, ho_offset=%ld\n",
                   hit_str[h->hits[i_hitobject].hit_type], distance,
                   p_keypress->offset, p_hitobject->offset);

            max_distance = max(max_distance, labs(distance));
            ++ p_keypress;
        }
    }

    print_hit_windows(window);
    printf("OD: %g\n", beatmap->OverallDifficulty);
    printf("max_distance: %ld\n", max_distance);
    return 0;
}

static void compute_hit_stats(int hit_stats[], osux_hit *hits, size_t hits_size)
{
    memset(hit_stats, 0, sizeof hit_stats[0] * MAX_HIT_TYPE);

    for (unsigned i = 0; i < hits_size; ++i)
        ++ hit_stats[hits[i].hit_type];
}

static void print_hit_stats(int hit_stats[])
{
    printf("300: %d\n", hit_stats[HIT_300]);
    printf("100: %d\n", hit_stats[HIT_100]);
    printf("50: %d\n", hit_stats[HIT_50]);
    printf("MISS: %d\n", hit_stats[HIT_MISS]);
}

int osux_hits_free(osux_hits *h)
{
    g_free(h->data);
    g_free(h->keypress);
    g_free(h->hits);

    return 0;
}

typedef int (*compute_hit_fn)(osux_hits*, osux_beatmap const*);
compute_hit_fn compute_mode[] = {
    [GAME_MODE_STD] = osux_hits_compute_hits_std_basic,
    [GAME_MODE_TAIKO] = osux_hits_compute_hits_taiko_basic,
    [GAME_MODE_CTB] = NULL,
    [GAME_MODE_MANIA] = NULL,
};

int osux_hits_init(osux_hits *hits,
                   osux_beatmap const *beatmap, osux_replay const *replay)
{
    memset(hits, 0, sizeof*hits);
    hits->game_mode = replay->game_mode;
    hits->overall_difficulty = beatmap->OverallDifficulty;
    hits->mods = replay->mods;

    if (replay->game_mode >= MAX_GAME_MODE)
        return -OSUX_ERR_INVALID_GAME_MODE;
    if (replay->game_mode != beatmap->Mode)
        return -OSUX_ERR_AUTOCONVERT_NOT_SUPPORTED;

    osux_hits_compute_data(hits, replay->data, replay->data_count);
    osux_hits_compute_keypress(hits);
    osux_hits_print_keypress(hits);

    if (hits->keypress == NULL) {
        osux_hits_free(hits);
        return -1;
    }

    compute_hit_fn compute = compute_mode[hits->game_mode];
    if (compute == NULL) {
        osux_hits_free(hits);
        return -OSUX_ERR_GAME_MODE_NOT_SUPPORTED;
    }

    (*compute)(hits, beatmap);

    if (hits->hits == NULL) {
        osux_hits_free(hits);
        return -OSUX_ERR_UNKNOWN_ERROR;
    }

    int hit_stats[MAX_HIT_TYPE];
    compute_hit_stats(hit_stats, hits->hits, hits->hits_size);
    print_hit_stats(hit_stats);

    return 0;
}


text:
import Actions from '../actions'
import React, {Component} from 'react'
import Store from '../store'
import TextareaInput from './textarea_input'

export default class LegendaryActions extends Component {
  constructor(props) {
    super(props)
    this.state = this.blankState()
    this.onBlur = this.onBlur.bind(this)
    this.onChange = this.onChange.bind(this)
  }

  blankState() {
    return {legendaryActions: ''}
  }

  componentDidMount() {
    Store.addChangeListener(()=>{
      this.setState({legendaryActions: Store.activeMonster.legendaryActions || ''})
    })
  }

  onChange(event) {
    this.setState({legendaryActions: event.target.value})
  }

  onBlur(event) {
    Actions.update({legendaryActions: event.target.value})
  }

  render() {
    return <div className='legendaryActions row'>
      <TextareaInput containerClassNames={['col', 's12']} id='legendaryActions'
        value={this.state.legendaryActions} onChange={this.onChange} onBlur={this.onBlur} label='Legendary Actions' />
    </div>
  }
}


text:
package com.hwyhard.www.fushihui.bean;

/**
 */

public class MusicItem {
    private String musicUrl;//歌曲链接
    private String musicPic;//图片链接

    public String getMusicLrc() {
        return musicLrc;
    }

    public void setMusicLrc(String musicLrc) {
        this.musicLrc = musicLrc;
    }

    private String musicLrc;//歌词
    public String getMusicUrl() {
        return musicUrl;
    }

    public void setMusicUrl(String musicUrl) {
        this.musicUrl = musicUrl;
    }

    public String getMusicPic() {
        return musicPic;
    }

    public void setMusicPic(String musicPic) {
        this.musicPic = musicPic;
    }

}


text:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Research.AbstractDomains.Expressions;
using Microsoft.Research.AbstractDomains;
using Microsoft.Research.AbstractDomains.Numerical;
using System.Diagnostics.Contracts;
using Microsoft.Research.DataStructures;

namespace Microsoft.Research.CodeAnalysis
{
  public static class BoxedExpressionsUtils
  {
    [ContractVerification(true)]
    public static List<BoxedExpression> SplitConjunctions(this BoxedExpression be)
    {
      Contract.Requires(be != null);
      Contract.Ensures(Contract.Result<List<BoxedExpression>>() != null);

      var result = new List<BoxedExpression>();
      return SplitHelper(BinaryOperator.LogicalAnd, be, result);
    }

    [ContractVerification(true)]
    public static List<BoxedExpression> SplitDisjunctions(this BoxedExpression be)
    {
      Contract.Requires(be != null);
      Contract.Ensures(Contract.Result<List<BoxedExpression>>() != null);

      var result = new List<BoxedExpression>();
      return SplitHelper(BinaryOperator.LogicalOr, be, result);
    }

    public static bool IsConstantTrue(this BoxedExpression be)
    {
      if (!be.IsConstant)
        return false;

      if (be.Constant is bool)
      {
        return ((bool)be.Constant);
      }

      return false;
    }

    /// <summary>
    /// Perform some rewritings to the boxed expressions, so that is is simplified, and it is nicer for a human reader
    /// </summary>
    public static BoxedExpression MakeItPrettier<Variable>(this BoxedExpression be, IExpressionDecoder<BoxedVariable<Variable>, BoxedExpression> decoder, IExpressionEncoder<BoxedVariable<Variable>, BoxedExpression> encoder)
    {
      Contract.Requires(encoder != null);

      var result = be;

      // 0. Do not do any work on MinValue <= exp, as -exp <= -MinValue is wrong
      BinaryOperator bop;
      BoxedExpression left, right;
      int maybeMinInt; long maybeMinLong;
      if(be.IsBinaryExpression(out bop, out left, out right) &&
        (bop == BinaryOperator.Cle || bop == BinaryOperator.Clt || bop == BinaryOperator.Cle_Un || bop == BinaryOperator.Clt_Un) &&
        ((left.IsConstantInt(out maybeMinInt) && maybeMinInt == Int32.MinValue) || (left.IsConstantInt64(out maybeMinLong) && maybeMinLong== Int64.MinValue))
        )
      {
        return result;
      }

      // 1. If it is a polynomial, do some arithmetic simplification, puts all the variables on one side, etc.
      Polynomial<BoxedVariable<Variable>, BoxedExpression> pol;
      if (Polynomial<BoxedVariable<Variable>, BoxedExpression>.TryToPolynomialForm(be, decoder, out pol))
      {
        if (pol.IsTautology)
        {
          return encoder.ConstantFor(true);
        }

        // m1 - m2 == 0 becomes m1 == m2
        BoxedVariable<Variable> x, y;
        Rational k;
        if (pol.TryMatch_XMinusYEqualk3(out x, out y, out k) && k.IsZero)
        {
          var xExp = encoder.VariableFor(x);
          var yExp = encoder.VariableFor(y);
          return encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.Equal, xExp, yExp);
        }

        result = pol.ToPureExpression(encoder);
      }

      // To do: add some more pretty printing there

      result = MakeItPrettier(result, x => encoder.ConstantFor(x));

      return result;
    }

    public static bool TryGetRange<Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly, Expression, Variable>(this Variable var, FlatDomain<Type> t,
      IDecodeMetaData<Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly> MetaDataDecoder, out IntervalStruct result)
      where Type: IEquatable<Type>
    {
      Contract.Requires(MetaDataDecoder != null);

      if (t.IsNormal)
      {
        var type = t.Value;
        if (MetaDataDecoder.System_Boolean.Equals(type) || MetaDataDecoder.System_Int32.Equals(type))
        {
          result = new IntervalStruct(Int32.MinValue, Int32.MaxValue, (Decimal d) => BoxedExpression.Const((int) d, MetaDataDecoder.System_Int32, MetaDataDecoder) );
          return true;
        }
        if (MetaDataDecoder.System_Char.Equals(type))
        {
          result = new IntervalStruct(Char.MinValue, Char.MaxValue, (Decimal d) => BoxedExpression.Const((char) d, MetaDataDecoder.System_Char, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_Int8.Equals(type))
        {
          result = new IntervalStruct(SByte.MinValue, SByte.MaxValue, (Decimal d) => BoxedExpression.Const((sbyte)d, MetaDataDecoder.System_Int8, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_Int16.Equals(type))
        {
          result = new IntervalStruct(short.MinValue, short.MaxValue, (Decimal d) => BoxedExpression.Const((short)d, MetaDataDecoder.System_Int16, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_Int64.Equals(type))
        {
          result = new IntervalStruct(long.MinValue, long.MaxValue, (Decimal d) => BoxedExpression.Const((long)d, MetaDataDecoder.System_Int64, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_UInt8.Equals(type))
        {
          result = new IntervalStruct(byte.MinValue, byte.MaxValue, (Decimal d) => BoxedExpression.Const((byte)d, MetaDataDecoder.System_UInt8, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_UInt16.Equals(type))
        {
          result = new IntervalStruct(UInt16.MinValue, UInt16.MaxValue, (Decimal d) => BoxedExpression.Const((UInt16)d, MetaDataDecoder.System_UInt16, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_UInt32.Equals(type))
        {
          result = new IntervalStruct(UInt32.MinValue, UInt32.MaxValue, (Decimal d) => BoxedExpression.Const((UInt32)d, MetaDataDecoder.System_UInt32, MetaDataDecoder));
          return true;
        }
        if (MetaDataDecoder.System_UInt64.Equals(type))
        {
          result = new IntervalStruct(UInt64.MinValue, UInt64.MaxValue, (Decimal d) => BoxedExpression.Const((UInt64)d, MetaDataDecoder.System_UInt64, MetaDataDecoder));
          return true;
        }

        // return false for Single, Double,
      }

      result = default(IntervalStruct);
      return false;
    }

    #region privates

    [ContractVerification(true)]
    private static List<BoxedExpression> SplitHelper(BinaryOperator bop, BoxedExpression be, List<BoxedExpression> result)
    {
      Contract.Requires(be != null);
      Contract.Requires(result != null);
      Contract.Ensures(Contract.Result<List<BoxedExpression>>() != null);

      if (be.IsBinary && be.BinaryOp == bop)
      {
        result = SplitHelper(bop, be.BinaryRight, SplitHelper(bop, be.BinaryLeft, result));
      }
      else
      {
        result.Add(be);
      }

      return result;
    }

    delegate BoxedExpression ConstFor(Int32 k);

    private static BoxedExpression MakeItPrettier(BoxedExpression result, ConstFor GetConst)
    {
      BinaryOperator binop;
      BoxedExpression left, right, mLeft, mRight;
      if (result.IsBinaryExpression(out binop, out left, out right))
      {
        #region All the cases
        switch (binop)
        {
          case BinaryOperator.Add:
          case BinaryOperator.Add_Ovf:
          case BinaryOperator.Add_Ovf_Un:
            return result;

          case BinaryOperator.And:
            return BoxedExpression.Binary(BinaryOperator.And, MakeItPrettier(left, GetConst), MakeItPrettier(right, GetConst));

          case BinaryOperator.Ceq:

            // -left == -right -> left == right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Ceq, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cge:
            // -left >= -right  -> left <= right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cle, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cge_Un:
            // -left >= -right  -> left <= right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cle_Un, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cgt:
            // -left > -right -> left < right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Clt, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cgt_Un:
            // -left > -right -> left < right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Clt_Un, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cle:
            // -left <= -right -> left >= right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cge, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cle_Un:
            // -left <= -right -> left >= right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cge_Un, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Clt:
            // -left < -right -> left > right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cgt, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Clt_Un:
            // -left < -right -> left > right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cgt_Un, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Cne_Un:
            // -left != -right -> left != right
            if (BothWithNegativeSigns(left, right, out mLeft, out mRight, GetConst))
            {
              return BoxedExpression.Binary(BinaryOperator.Cne_Un, mLeft, mRight);
            }
            else
            {
              return result;
            }

          case BinaryOperator.Div:
          case BinaryOperator.Div_Un:
          case BinaryOperator.Mul:
          case BinaryOperator.Mul_Ovf:
          case BinaryOperator.Mul_Ovf_Un:
            return result;

          case BinaryOperator.Or:
            return BoxedExpression.Binary(BinaryOperator.Or, MakeItPrettier(left, GetConst), MakeItPrettier(right, GetConst));

          case BinaryOperator.Rem:
          case BinaryOperator.Rem_Un:
          case BinaryOperator.Shl:
          case BinaryOperator.Shr:
          case BinaryOperator.Shr_Un:
          case BinaryOperator.Sub:
          case BinaryOperator.Sub_Ovf:
          case BinaryOperator.Sub_Ovf_Un:
          case BinaryOperator.Xor:
            return result;

          // Should be unreachable
          default:
            return result;

        }
        #endregion
      }
      else
      {
        return result;
      }
    }

    private static bool BothWithNegativeSigns(BoxedExpression left, BoxedExpression right, out BoxedExpression minusLeft, out BoxedExpression minusRight, ConstFor GetConst)
    {
      if (left.IsUnary && left.UnaryOp == UnaryOperator.Neg)
      {
        // case -left, -right
        if (right.IsUnary && right.UnaryOp == UnaryOperator.Neg)
        {
          minusLeft = left.UnaryArgument;
          minusRight = right.UnaryArgument;

          return true;
        }

        Int32 value;
        // case -left, constant
        if (right.IsConstant && TryInt32Constant(right.Constant, out value))
        {
          minusLeft = left.UnaryArgument;
          minusRight = GetConst(-value);

          return true;
        }

      }
      else if (right.IsUnary && right.UnaryOp == UnaryOperator.Neg)
      {
        Int32 value;
        // case constant, -right
        if (left.IsConstant && TryInt32Constant(left.Constant, out value))
        {
          minusLeft = GetConst(-value);
          minusRight = right.UnaryArgument;

          return true;
        }
      }

      minusLeft = minusRight = null;
      return false;
    }

    private static bool TryInt32Constant(object o, out Int32 value)
    {
      if (o is Int32)
      {
        value = (Int32)o;
        return true;
      }
      else if (o is Int64)
      {
        Int64 asInt64 = (Int64)o;
        if (asInt64 >= Int32.MinValue && asInt64 <= Int32.MaxValue)
        {
          value = (Int32)asInt64;
          return true;
        }
      }
      value = -2345;
      return false;
    }

    #endregion
  }
}


text:
class Project < ApplicationRecord
  has_many :additional_rights, dependent: :destroy
  cattr_accessor :skip_callbacks
  # We could add something like this:
  # + has_many :users, through: :additional_rights
  # but we don't, because we don't use the other information about those users.
  # We only need the user_ids and the additional_rights table has that.

  using StringRefinements
  using SymbolRefinements

  include PgSearch::Model # PostgreSQL-specific text search

  # When did we add met_justification_required?
  STATIC_ANALYSIS_JUSTIFICATION_REQUIRED_DATE =
    Time.iso8601('2017-04-25T00:00:00Z')

  # When did we first show an explicit license for the data
  # (CC-BY-3.0+)?
  ENTRY_LICENSE_EXPLICIT_DATE = Time.iso8601('2017-02-20T12:00:00Z')

  STATUS_CHOICE = %w[? Met Unmet].freeze
  STATUS_CHOICE_NA = (STATUS_CHOICE + %w[N/A]).freeze
  MIN_SHOULD_LENGTH = 5
  MAX_TEXT_LENGTH = 8192 # Arbitrary maximum to reduce abuse
  MAX_SHORT_STRING_LENGTH = 254 # Arbitrary maximum to reduce abuse

  # All badge level internal names *including* in_progress
  # NOTE: If you add a new level, modify compute_tiered_percentage
  BADGE_LEVELS = %w[in_progress passing silver gold].freeze

  # All badge level internal names that indicate *completion*,
  # so COMPLETED_BADGE_LEVELS[0] is 'passing'.
  # Note: This is the *internal* lowercase name, e.g., for field names.
  # For *printed* names use t("projects.form_early.level.#{level}")
  # Note that drop() does NOT mutate the original value.
  COMPLETED_BADGE_LEVELS = BADGE_LEVELS.drop(1).freeze

  # All badge levels as IDs. Useful for enumerating "all levels" as:
  # Project::LEVEL_IDS.each do |level| ... end
  LEVEL_ID_NUMBERS = (0..(COMPLETED_BADGE_LEVELS.length - 1)).freeze
  LEVEL_IDS = LEVEL_ID_NUMBERS.map(&:to_s)

  PROJECT_OTHER_FIELDS = %i[
    name description homepage_url repo_url cpe implementation_languages
    license general_comments user_id disabled_reminders lock_version
    level additional_rights_changes
  ].freeze
  ALL_CRITERIA_STATUS = Criteria.all.map(&:status).freeze
  ALL_CRITERIA_JUSTIFICATION = Criteria.all.map(&:justification).freeze
  PROJECT_PERMITTED_FIELDS = (PROJECT_OTHER_FIELDS + ALL_CRITERIA_STATUS +
                              ALL_CRITERIA_JUSTIFICATION).freeze

  default_scope { order(:created_at) }

  scope :created_since, (
    lambda do |time|
      where(Project.arel_table[:created_at].gteq(time))
    end
  )

  scope :gteq, (
    lambda do |floor|
      where(Project.arel_table[:tiered_percentage].gteq(floor.to_i))
    end
  )

  scope :in_progress, -> { lteq(99) }

  scope :lteq, (
    lambda do |ceiling|
      where(Project.arel_table[:tiered_percentage].lteq(ceiling.to_i))
    end
  )

  scope :passing, -> { gteq(100) }

  scope :recently_updated, (
    lambda do
      # The "includes" here isn't ideal.
      # Originally we used "eager_load" on :user, but
      # "eager_load" forces a load of *all* fields per a bug in Rails:
      # https://github.com/rails/rails/issues/15185
      # Switching to ".includes" fixes the bug, though it means we do 2
      # database queries instead of just one.
      # We could use the gem "rails_select_on_includes" to fix this bug:
      # https://github.com/alekseyl/rails_select_on_includes
      # but that's something of a hack.
      # If a totally-cached feed is used, then the development environment
      # will complain as follows:
      # GET /feed
      # AVOID eager loading detected
      #   Project => [:user]
      #   Remove from your finder: :includes => [:user]
      # However, you *cannot* simply remove the includes, because
      # when the feed is *not* completely cached, the code *does* need
      # this user data.
      limit(50).reorder(updated_at: :desc, id: :asc).includes(:user)
    end
  )

  # prefix query (old search system)
  scope :text_search, (
    lambda do |text|
      start_text = "#{sanitize_sql_like(text)}%"
      where(
        Project.arel_table[:name].matches(start_text).or(
          Project.arel_table[:homepage_url].matches(start_text)
        ).or(
          Project.arel_table[:repo_url].matches(start_text)
        )
      )
    end
  )

  # Search for exact match on URL
  # (home page, repo, and maybe package URL someday)
  # We have indexes on each of these columns, so this will be fast.
  # We remove trailing space and slash to make it quietly "work as expected".
  scope :url_search, (
    lambda do |url|
      clean_url = url.chomp(' ').chomp('/')
      where('homepage_url = ? OR repo_url = ?', clean_url, clean_url)
    end
  )

  # Use PostgreSQL-specific text search mechanism
  # There are many options we aren't currently using; for more info, see:
  # https://github.com/Casecommons/pg_search
  pg_search_scope(
    :search_for,
    against: %i[name homepage_url repo_url description]
    # using: { tsearch: { any_word: true } }
  )

  scope :updated_since, (
    lambda do |time|
      where(Project.arel_table[:updated_at].gteq(time))
    end
  )

  # Record information about a project.
  # We'll also record previous versions of information:
  has_paper_trail

  before_save :update_badge_percentages, unless: :skip_callbacks

  # A project is associated with a user
  belongs_to :user
  delegate :name, to: :user, prefix: true # Support "user_name"
  delegate :nickname, to: :user, prefix: true # Support "user_nickname"

  # For these fields we'll have just simple validation rules.
  # We'll rely on Rails' HTML escaping system to counter XSS.
  validates :name, length: { maximum: MAX_SHORT_STRING_LENGTH }, text: true
  validates :description, length: { maximum: MAX_TEXT_LENGTH }, text: true
  validates :license, length: { maximum: MAX_SHORT_STRING_LENGTH }, text: true
  validates :general_comments, text: true

  # We'll do automated analysis on these URLs, which means we will *download*
  # from URLs provided by untrusted users.  Thus we'll add additional
  # URL restrictions to counter tricks like http://ACCOUNT:PASSWORD@host...
  # and http://something/?arbitrary_parameters

  validates :repo_url, url: true, length: { maximum: MAX_SHORT_STRING_LENGTH },
                       uniqueness: { allow_blank: true }
  validates :homepage_url,
            url: true,
            length: { maximum: MAX_SHORT_STRING_LENGTH }
  validate :need_a_base_url

  # Comma-separated list.  This is very generous in what characters it
  # allows in a programming language name, but restricts it to ASCII and omits
  # problematic characters that are very unlikely in a name like
  # <, >, &, ", brackets, and braces.  This handles language names like
  # JavaScript, C++, C#, D-, and PL/I.  A space is optional after a comma.
  # We have to allow embedded spaces, e.g., "Jupyter Notebook".
  VALID_LANGUAGE_LIST =
    %r{\A(|-| ([A-Za-z0-9!\#$%'()*+.\/\:;=?@\[\]^~ -]+
        (,\ ?[A-Za-z0-9!\#$%'()*+.\/\:;=?@\[\]^~ -]+)*))\Z}x.freeze
  validates :implementation_languages,
            length: { maximum: MAX_SHORT_STRING_LENGTH },
            format: {
              with: VALID_LANGUAGE_LIST,
              message: :comma_separated_list
            }

  validates :cpe,
            length: { maximum: MAX_SHORT_STRING_LENGTH },
            format: {
              with: /\A(cpe:.*)?\Z/,
              message: :begin_with_cpe
            }

  validates :user_id, presence: true

  Criteria.each_value do |criteria|
    criteria.each_value do |criterion|
      if criterion.na_allowed?
        validates criterion.name.status, inclusion: { in: STATUS_CHOICE_NA }
      else
        validates criterion.name.status, inclusion: { in: STATUS_CHOICE }
      end
      validates criterion.name.justification,
                length: { maximum: MAX_TEXT_LENGTH },
                text: true
    end
  end

  # Return a string representing the additional rights on this project.
  # Currently it's just a (possibly empty) list of user ids from
  # AdditionalRight.  If AdditionalRights gains different kinds of rights
  # (e.g., to spec additional owners), this method will need to be tweaked.
  def additional_rights_to_s
    # "distinct" shouldn't be needed; it's purely defensive here
    list = AdditionalRight.where(project_id: id).distinct.pluck(:user_id)
    list.sort.to_s # Use list.sort.to_s[1..-2] to remove surrounding [ and ]
  end

  # Return string representing badge level; assumes tiered_percentage correct.
  # This returns 'in_progress' if we aren't passing yet.
  # See method badge_level if you want 'in_progress' for < 100.
  # See method badge_value if you want the specific percentage for in_progress.
  def badge_level
    # This is *integer* division, so it truncates.
    BADGE_LEVELS[tiered_percentage / 100]
  end

  def calculate_badge_percentage(level)
    active = Criteria.active(level)
    met = active.count { |criterion| enough?(criterion) }
    to_percentage met, active.size
  end

  # Does this contain a URL *anywhere* in the (justification) text?
  # Note: This regex needs to be logically the same as the one used in the
  # client-side badge calculation, or it may confuse some users.
  # See app/assets/javascripts/*.js function "containsURL".
  #
  # Note that we do NOT need to validate these URLs, because the BadgeApp
  # 1. escapes these (as part of normal processing) against XSS attacks, and
  # 2. does not traverse these URLs in its automated processing.
  # Thus, this rule is intentionally *not* strict at all.  Contrast this
  # with the intentionally strict validation of the project and repo URLs,
  # which *are* traversed by BadgeApp and thus need to be much more strict.
  #
  def contains_url?(text)
    return false if !text || text.start_with?('// ')

    text =~ %r{https?://[^ ]{5}}
  end

  # Returns a symbol indicating a the status of an particular criterion
  # in a project.  These are:
  # :criterion_passing -
  #   'Met' (or 'N/A' if applicable) has been selected for the criterion
  #   and all requred justification text (including url's) have been entered  #
  # :criterion_failing -
  #   'Unmet' has been selected for a MUST criterion'.
  # :criterion_barely -
  #   'Unmet' has been selected for a SHOULD or SUGGESTED criterion and
  #   ,if SHOULD, required justification text has been entered.
  # :criterion_url_required -
  #   'Met' has been selected, but a required url in the justification
  #   text is missing.
  # :criterion_justification_required -
  #   Required justification for 'Met', 'N/A' or 'Unmet' selection is missing.
  # :criterion_unknown -
  #   The criterion has been left at it's default value and thus the status
  #   is unknown.
  # This method is mirrored in assets/project-form.js as getCriterionResult
  # If you change this method, change getCriterionResult accordingly.
  def get_criterion_result(criterion)
    status = self[criterion.name.status]
    justification = self[criterion.name.justification]
    return :criterion_unknown if status.unknown?
    return get_met_result(criterion, justification) if status.met?
    return get_unmet_result(criterion, justification) if status.unmet?

    get_na_result(criterion, justification)
  end

  def get_satisfaction_data(level, panel)
    total =
      Criteria[level].values.select do |criterion|
        criterion.major.downcase.delete(' ') == panel
      end
    passing = total.count { |criterion| enough?(criterion) }
    {
      text: "#{passing}/#{total.size}",
      color: get_color(passing / [1, total.size.to_f].max)
    }
  end

  # Return the badge value: 0..99 (the percent) if in progress,
  # else it returns 'passing', 'silver', or 'gold'.
  # This presumes that tiered_percentage has already been calculated.
  # See method badge_level if you want 'in_progress' for < 100.
  def badge_value
    if tiered_percentage < 100
      tiered_percentage
    else
      # This is *integer* division, so it truncates.
      BADGE_LEVELS[tiered_percentage / 100]
    end
  end

  # Return this project's image src URL for its badge image (SVG).
  # * If the project entry has changed relatively recently,
  # we give its /badge_static value.  That way, the user sees the
  # correct result even if the CDN hasn't completed distributing the
  # new value or a bad key prevents its update.
  # * If the project entry has NOT changed relatively recently,
  # we give the /projects/:id/badge value, so that humans who copy the
  # values without reading directions are more likely to see the URL that
  # we want them to use in READMEs. We also include a comment in the HTML
  # view telling people to use the /projects/:id/badge URL, all to encourage
  # humans to use the correct URL.
  def badge_src_url
    if updated_at > 24.hours.ago # Has this entry changed relatively recently?
      "/badge_static/#{badge_value}"
    else
      "/projects/#{id}/badge"
    end
  end

  # Flash a message to update static_analysis if the user is updating
  # for the first time since we added met_justification_required that
  # criterion

  def notify_for_static_analysis?(level)
    status = self[Criteria[level][:static_analysis].name.status]
    result = get_criterion_result(Criteria[level][:static_analysis])
    updated_at < STATIC_ANALYSIS_JUSTIFICATION_REQUIRED_DATE &&
      status.met? && result == :criterion_justification_required
  end

  # Send owner an email they add a new project.
  def send_new_project_email
    ReportMailer.email_new_project_owner(self).deliver_now
  end

  # Return true if we should show an explicit license for the data.
  # Old entries did not set a license; we only want to show entry licenses
  # if the updated_at field indicates there was agreement to it.
  def show_entry_license?
    updated_at >= ENTRY_LICENSE_EXPLICIT_DATE
  end

  # Update the badge percentage for a given level (expressed as a number;
  # 0=passing), and update relevant event datetime if needed.
  # It presumes the lower-level percentages (if relevant) are calculated.
  def update_badge_percentage(level, current_time)
    old_badge_percentage = self["badge_percentage_#{level}".to_sym]
    update_prereqs(level) unless level.to_i.zero?
    self["badge_percentage_#{level}".to_sym] =
      calculate_badge_percentage(level)
    update_passing_times(level, old_badge_percentage, current_time)
  end

  # Compute the 'tiered percentage' value 0..300. This gives partial credit,
  # but only if you've completed a previous level.
  def compute_tiered_percentage
    if badge_percentage_0 < 100
      badge_percentage_0
    elsif badge_percentage_1 < 100
      badge_percentage_1 + 100
    else
      badge_percentage_2 + 200
    end
  end

  def update_tiered_percentage
    self.tiered_percentage = compute_tiered_percentage
  end

  # Update the badge percentages for all levels.
  def update_badge_percentages
    # Create a single datetime value so that they are consistent
    current_time = Time.now.utc
    Project::LEVEL_IDS.each do |level|
      update_badge_percentage(level, current_time)
    end
    update_tiered_percentage # Update the 'tiered_percentage' number 0..300
  end

  # Return owning user's name for purposes of display.
  def user_display_name
    user_name || user_nickname
  end

  # Update badge percentages for all project entries, and send emails
  # to any project where this causes loss or gain of a badge.
  # Use this after the badging rules have changed.
  # We precalculate and store percentages in the database;
  # this speeds up many actions, but it means that a change in the rules
  # doesn't automatically change the precalculated values.
  # rubocop:disable Metrics/MethodLength
  def self.update_all_badge_percentages(levels)
    raise TypeError, 'levels must be an Array' unless levels.is_a?(Array)

    levels.each do |l|
      raise ArgumentError, "Invalid level: #{l}" unless l.in? Criteria.keys
    end
    Project.skip_callbacks = true
    Project.find_each do |project|
      project.with_lock do
        # Create a single datetime value so that they are consistent
        current_time = Time.now.utc
        levels.each do |level|
          project.update_badge_percentage(level, current_time)
        end
        project.update_tiered_percentage
        project.save!(touch: false)
      end
    end
    Project.skip_callbacks = false
  end
  # rubocop:enable Metrics/MethodLength

  # The following configuration options are trusted.  Set them to
  # reasonable numbers or accept the defaults.

  # Maximum number of reminders to send by email at one time.
  # We want a rate limit to avoid being misinterpreted as a spammer,
  # and also to limit damage if there's a mistake in the code.
  # By default, start very low until we're confident in the code.
  MAX_REMINDERS = (ENV['BADGEAPP_MAX_REMINDERS'] || 2).to_i

  # Minimum number of days since last lost a badge before sending reminder,
  # if it lost one.
  LOST_PASSING_REMINDER = (ENV['BADGEAPP_LOST_PASSING_REMINDER'] || 30).to_i

  # Minimum number of days since project last updated before sending reminder
  LAST_UPDATED_REMINDER = (ENV['BADGEAPP_LAST_UPDATED_REMINDER'] || 30).to_i

  # Minimum number of days since project was last sent a reminder
  LAST_SENT_REMINDER = (ENV['BADGEAPP_LAST_SENT_REMINDER'] || 60).to_i

  # Return which projects should be reminded to work on their badges.  See:
  # https://github.com/coreinfrastructure/best-practices-badge/issues/487
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  def self.projects_to_remind
    # This is computed entirely using the ActiveRecord query interface
    # as a single select+sort+limit, and not implemented using methods or
    # direct SQL commands. Using the ActiveRecord query interface will turn
    # this directly into a single database request, which will be blazingly
    # fast regardless of the database size (via the indexes). Method
    # invocations would be super-slow, and direct SQL commands will be less
    # portable than ActiveRecord's interface (which works to paper over
    # differences between SQL engines).
    #
    # Select projects eligible for reminders =
    #   in_progress and not_recently_lost_badge and not_disabled_reminders
    #   and inactive and not_recently_reminded and valid_email.
    # where these terms are defined as:
    #   in_progress = badge_percentage less than 100%.
    #   not_recently_lost_badge = lost_passing_at IS NULL OR
    #     less than LOST_PASSING_REMINDER (30) days ago
    #   not_disabled_reminders = not(project.disabled_reminders), default false
    #   inactive = updated_at is LAST_UPDATED_REMINDER (30) days ago or more
    #   not_recently_reminded = last_reminder_at IS NULL OR
    #     more than 60 days ago. Notice that if recently_reminded is null
    #     (no reminders have been sent), only the other criteria matter.
    #   valid_email = users.encrypted_email (joined) is not null
    # Prioritize. Sort by the last_reminder_at datetime
    #   (use updated_at if last_reminder_at is null), oldest first.
    #   Since last_reminder_at gets updated with a newer datetime when
    #   we send a message, each email we send will lower its reminder
    #   priority. Thus we will eventually cycle through all inactive projects
    #   if none of them respond to reminders.
    #   Use: projects.order("COALESCE(last_reminder_at, updated_at)")
    #   We cannot check if email includes "@" here, because they are
    #   encrypted (the database does not have access to the keys, by intent).
    #
    # The "reorder" below uses "Arel.sql" to work around
    # a deprecation warning from Rails 5.2, and
    # is not expected to work in Rails 6.  The warning is as follows:
    # DEPRECATION WARNING: Dangerous query method
    # (method whose arguments are used as raw SQL) called with
    # non-attribute argument(s): "COALESCE(last_reminder_at,
    # projects.updated_at)". Non-attribute arguments will be
    # disallowed in Rails 6.0. This method should not be called with
    # user-provided values, such as request parameters or model
    # attributes. Known-safe values can be passed by wrapping
    # them in Arel.sql().
    # For now we'll wrap them as required.  This is unfortunate; it would
    # dangerous if user-provided data was used, but that is not the case.
    # We're hoping Rails 6 will give us an alternative construct.
    # If not, alternatives include creating a calculated field
    # (e.g., one that does the coalescing).
    Project
      .select('projects.*, users.encrypted_email as user_encrypted_email')
      .where('badge_percentage_0 < 100')
      .where('lost_passing_at IS NULL OR lost_passing_at < ?',
             LOST_PASSING_REMINDER.days.ago)
      .where('disabled_reminders = FALSE')
      .where('projects.updated_at < ?',
             LAST_UPDATED_REMINDER.days.ago)
      .where('last_reminder_at IS NULL OR last_reminder_at < ?',
             LAST_SENT_REMINDER.days.ago)
      .joins(:user).references(:user) # Need this to check email address
      .where('user_id IS NOT NULL') # Safety check
      .where('users.encrypted_email IS NOT NULL')
      .reorder(Arel.sql('COALESCE(last_reminder_at, projects.updated_at)'))
      .first(MAX_REMINDERS)
  end
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength

  # Return which projects should be announced as getting badges in the
  # month target_month with level (as a number, 0=passing)
  def self.projects_first_in(level, target_month)
    # Defense-in-depth: ensure 'level' is a valid value.
    return unless LEVEL_ID_NUMBERS.member?(level)

    name = COMPLETED_BADGE_LEVELS[level] # level name, e.g. 'passing'
    # We could omit listing projects which have lost & regained their
    # badge by adding this line:
    # .where('lost_#{name}_at IS NULL')
    # However, it seems reasonable to note projects that have lost their
    # badge but have since regained it (especially since it could have
    # happened within this month!). After all, we want to encourage
    # projects that have lost their badge levels to regain them.
    Project
      .select("id, name, achieved_#{name}_at")
      .where("badge_percentage_#{level} >= 100")
      .where("achieved_#{name}_at >= ?", target_month.at_beginning_of_month)
      .where("achieved_#{name}_at <= ?", target_month.at_end_of_month)
      .reorder("achieved_#{name}_at")
  end

  def self.recently_reminded
    Project
      .select('projects.*, users.encrypted_email as user_encrypted_email')
      .joins(:user).references(:user) # Need this to check email address
      .where('last_reminder_at IS NOT NULL')
      .where('last_reminder_at >= ?', 14.days.ago)
      .reorder('last_reminder_at')
  end

  private

  # def all_active_criteria_passing?
  #   Criteria.active.all? { |criterion| enough? criterion }
  # end

  WHAT_IS_ENOUGH = %i[criterion_passing criterion_barely].freeze

  # This method is mirrored in assets/project-form.js as isEnough
  # If you change this method, change isEnough accordingly.
  def enough?(criterion)
    result = get_criterion_result(criterion)
    WHAT_IS_ENOUGH.include?(result)
  end

  # This method is mirrored in assets/project-form.js as getColor
  # If you change this method, change getColor accordingly.
  def get_color(value)
    hue = (value * 120).round
    "hsl(#{hue}, 100%, 50%)"
  end

  # This method is mirrored in assets/project-form.js as getMetResult
  # If you change this method, change getMetResult accordingly.
  def get_met_result(criterion, justification)
    return :criterion_url_required if criterion.met_url_required? &&
                                      !contains_url?(justification)
    return :criterion_justification_required if
      criterion.met_justification_required? &&
      !justification_good?(justification)

    :criterion_passing
  end

  # This method is mirrored in assets/project-form.js as getNAResult
  # If you change this method, change getNAResult accordingly.
  def get_na_result(criterion, justification)
    return :criterion_justification_required if
      criterion.na_justification_required? &&
      !justification_good?(justification)

    :criterion_passing
  end

  # This method is mirrored in assets/project-form.js as getUnmetResult
  # If you change this method, change getUnmetResult accordingly.
  def get_unmet_result(criterion, justification)
    return :criterion_barely if criterion.suggested? || (criterion.should? &&
                               justification_good?(justification))
    return :criterion_justification_required if criterion.should?

    :criterion_failing
  end

  def justification_good?(justification)
    return false if justification.nil? || justification.start_with?('// ')

    justification.length >= MIN_SHOULD_LENGTH
  end

  def need_a_base_url
    return unless repo_url.blank? && homepage_url.blank?

    errors.add :base, I18n.t('error_messages.need_home_page_or_url')
  end

  def to_percentage(portion, total)
    return 0 if portion.zero?
    return 100 if portion >= total

    # Give percentage, but only up to 99% (so "100%" always means "complete")
    # The tertiary operator is clearer & faster than using [...].min
    result = ((portion * 100.0) / total).round
    result > 99 ? 99 : result
  end

  # Update achieved_..._at & lost_..._at fields given level as number
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  def update_passing_times(level, old_badge_percentage, current_time)
    level_name = COMPLETED_BADGE_LEVELS[level.to_i] # E.g., 'passing'
    current_percentage = self["badge_percentage_#{level}".to_sym]
    # If something is wrong, don't modify anything!
    return if current_percentage.blank? || old_badge_percentage.blank?

    current_percentage_i = current_percentage.to_i
    old_badge_percentage_i = old_badge_percentage.to_i
    if current_percentage_i >= 100 && old_badge_percentage_i < 100
      self["achieved_#{level_name}_at".to_sym] = current_time
      first_achieved_field = "first_achieved_#{level_name}_at".to_sym
      if self[first_achieved_field].blank? # First time? Set that too!
        self[first_achieved_field] = current_time
      end
    elsif current_percentage_i < 100 && old_badge_percentage_i >= 100
      self["lost_#{level_name}_at".to_sym] = current_time
    end
  end
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
  # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity

  # Given numeric level 1+, set the value of
  # achieve_{previous_level_name}_status to either Met or Unmet, based on
  # the achievement of the *previous* level. This is a simple way to ensure
  # that to pass level X when X > 0, you must meet the criteria of level X-1.
  # We *only* set the field if it currently has a different value.
  # When filling in the prerequisites, we do not fill in the justification
  # for them. The justification is only there as it makes implementing this
  # portion of the code simpler.
  def update_prereqs(level)
    level = level.to_i
    return if level <= 0

    # The following works because BADGE_LEVELS[1] is 'passing', etc:
    achieved_previous_level = "achieve_#{BADGE_LEVELS[level]}_status".to_sym

    if self["badge_percentage_#{level - 1}".to_sym] >= 100
      return if self[achieved_previous_level] == 'Met'

      self[achieved_previous_level] = 'Met'
    else
      return if self[achieved_previous_level] == 'Unmet'

      self[achieved_previous_level] = 'Unmet'
    end
  end
end
# rubocop:enable Metrics/ClassLength


text:
pub type Handle = u64;

#[derive(Debug, Default, PartialEq)]
pub struct HandleGenerator {
    last_handle: Handle,
}

impl HandleGenerator {
    pub fn new() -> HandleGenerator {
        HandleGenerator::default()
    }

    pub fn generate(&mut self) -> Handle {
        self.last_handle += 1;
        self.last_handle
    }
}