text:
package org.deeplearning4j.nn.modelimport.keras;

import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.FloatPointer;
import org.bytedeco.javacpp.hdf5;
import org.deeplearning4j.berkeley.StringUtils;
import org.deeplearning4j.nn.api.Layer;
import org.deeplearning4j.nn.conf.MultiLayerConfiguration;
import org.deeplearning4j.nn.conf.ComputationGraphConfiguration;
import org.deeplearning4j.nn.graph.ComputationGraph;
import org.deeplearning4j.nn.layers.convolution.ConvolutionLayer;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.factory.Nd4j;
import org.nd4j.shade.jackson.databind.DeserializationFeature;
import org.nd4j.shade.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.bytedeco.javacpp.hdf5.H5F_ACC_RDONLY;
import static org.bytedeco.javacpp.hdf5.H5O_TYPE_DATASET;
import static org.bytedeco.javacpp.hdf5.H5O_TYPE_GROUP;
import static org.deeplearning4j.nn.modelimport.keras.ModelConfiguration.extractWeightsMetadataFromConfig;
import static org.deeplearning4j.nn.modelimport.keras.ModelConfiguration.importFunctionalApiConfig;
import static org.deeplearning4j.nn.modelimport.keras.ModelConfiguration.importSequentialModelConfig;

/**
 * Routines for importing saved Keras models.
 *
 * @author davekale
 */
public class Model {
    private static Logger log = LoggerFactory.getLogger(Model.class);

    private Model() {}

    /**
     * Imports a Keras Sequential model saved using model.save_model(...). Model
     * configuration and weights are loaded from single HDF5 archive.
     *
     * @param  modelHdf5Filename path to HDF5 archive storing Keras Sequential model
     * @return                   DL4J MultiLayerNetwork
     * @throws IOException
     * @throws IncompatibleKerasConfigurationException
     * @throws UnsupportedOperationException
     * @see    MultiLayerNetwork
     * @see    MultiLayerConfiguration
     *
     * TODO: remove this once we have a shared model interface?
     */
    public static MultiLayerNetwork importSequentialModel(String modelHdf5Filename)
            throws IOException, IncompatibleKerasConfigurationException, UnsupportedOperationException {
        MultiLayerNetwork model = importModel(modelHdf5Filename, true);
        return model;
    }

    /**
     * Imports a Keras Functional API model saved using model.save_model(...). Model
     * configuration and weights are loaded from single HDF5 archive.
     *
     * @param modelHdf5Filename  path to HDF5 archive storing Keras Functional API model
     * @return                   DL4J ComputationGraph
     * @throws IOException
     * @throws IncompatibleKerasConfigurationException
     * @throws UnsupportedOperationException
     * @see    ComputationGraph
     * @see    ComputationGraphConfiguration
     *
     * TODO: remove this once we have a shared model interface?
     */
    public static ComputationGraph importFunctionalApiModel(String modelHdf5Filename)
            throws IOException, IncompatibleKerasConfigurationException, UnsupportedOperationException {
        ComputationGraph model = importModel(modelHdf5Filename, false);
        return model;
    }

    /**
     * Load Keras model saved using model.save_model(...).
     *
     * @param modelHdf5Filename  path to HDF5 archive storing Keras model
     * @param isSequential       whether the model to be loaded is Sequential
     * @param <T>
     * @return                   DL4J MultiLayerNetwork or ComputationGraph
     * @throws IOException
     *
     * TODO: make public and change return type to shared model interface once we have one.
     */
    private static <T> T importModel(String modelHdf5Filename, boolean isSequential) throws IOException {
        /* Open model HDF5 file. */
        hdf5.H5File file = new hdf5.H5File(modelHdf5Filename, H5F_ACC_RDONLY);
        /* Read model config JSON string from "model_config" attribute. */
        hdf5.Attribute attr = file.openAttribute("model_config");
        hdf5.VarLenType vl = attr.getVarLenType();
        int bufferSizeMult = 1;
        String configJson = null;
        /* TODO: find a less hacky way to do this.
         * Reading variable length strings (from attributes) is a giant
         * pain. There does not appear to be any way to determine the
         * length of the string in advance, so we use a hack: choose a
         * buffer size and read the config. If Jackson fails to parse
         * it, then we must not have read the entire config. Increase
         * buffer and repeat.
         */
        while (true) {
            byte[] attrBuffer = new byte[bufferSizeMult * 2000];
            BytePointer attrPointer = new BytePointer(attrBuffer);
            attr.read(vl, attrPointer);
            attrPointer.get(attrBuffer);
            configJson = new String(attrBuffer);
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
            try {
                mapper.readTree(configJson);
                break;
            } catch (IOException e) {}
            bufferSizeMult++;
            if (bufferSizeMult > 100) {
                throw new IncompatibleKerasConfigurationException("Could not read abnormally long Keras config. Please file an issue!");
            }
        }
        T model = importModel(configJson, file.asCommonFG().openGroup("/model_weights"), isSequential);
        file.close();
        return model;
    }

    /**
     * Imports a Keras Sequential model where the config and weights were saved
     * separately using calls to model.to_json() and model.save_weights(...).
     *
     * @param configJsonFilename   path to JSON file storing Keras Sequential model configuration
     * @param weightsHdf5Filename  path to HDF5 archive storing Keras Sequential model weights
     * @return                     DL4J MultiLayerNetwork
     * @throws IOException
     * @throws IncompatibleKerasConfigurationException
     * @throws UnsupportedOperationException
     * @see MultiLayerNetwork
     * @see MultiLayerConfiguration
     *
     * TODO: remove this once we have a shared model interface?
     */
    public static MultiLayerNetwork importSequentialModel(String configJsonFilename, String weightsHdf5Filename)
            throws IOException, IncompatibleKerasConfigurationException, UnsupportedOperationException {
        MultiLayerNetwork model = importModel(configJsonFilename, weightsHdf5Filename, true);
        return model;
    }

    /**
     * Imports a Keras Functional API model where the config and weights were saved
     * separately using calls to model.to_json() and model.save_weights(...).
     *
     * @param configJsonFilename   path to JSON file storing Keras Functional API model configuration
     * @param weightsHdf5Filename  path to HDF5 archive storing Keras Functional API model weights
     * @return                     DL4J ComputationGraph
     * @throws IOException
     * @throws IncompatibleKerasConfigurationException
     * @throws UnsupportedOperationException
     * @see ComputationGraph
     * @see ComputationGraphConfiguration
     *
     * TODO: remove this once we have a shared model interface?
     */
    public static ComputationGraph importModel(String configJsonFilename, String weightsHdf5Filename)
            throws IOException, IncompatibleKerasConfigurationException, UnsupportedOperationException {
        ComputationGraph model = importModel(configJsonFilename, weightsHdf5Filename, false);
        return model;
    }

    /**
     * Load Keras model where the config and weights were saved separately using calls to
     * model.to_json() and model.save_weights(...).
     *
     * @param configJsonFilename   path to JSON file storing Keras Functional API model configuration
     * @param weightsHdf5Filename  path to HDF5 archive storing Keras Functional API model weights
     * @param isSequential         whether the model to be loaded is Sequential
     * @param <T>
     * @return                     DL4J MultiLayerNetwork or ComputationGraph
     * @throws IOException
     * @throws IncompatibleKerasConfigurationException
     * @throws UnsupportedOperationException
     *
     * TODO: make public and change return type to shared model interface once we have one.
     */
    private static <T> T importModel(String configJsonFilename, String weightsHdf5Filename, boolean isSequential)
            throws IOException, IncompatibleKerasConfigurationException, UnsupportedOperationException {
        String configJson = new String(Files.readAllBytes(Paths.get(configJsonFilename)));
        hdf5.H5File file = new hdf5.H5File();
        file.openFile(weightsHdf5Filename, H5F_ACC_RDONLY);
        T model = importModel(configJson, file.asCommonFG().openGroup("/"), isSequential);
        file.close();
        return model;
    }

    /**
     * Helper function for importing Keras models.
     *
     * @param configJson    JSON string storing Keras model configuration
     * @param weightsGroup  root HDF5 Group storing all Keras weights for single model
     * @param isSequential  whether the model to be loaded is Sequential
     * @param <T>
     * @return              DL4J MultiLayerNetwork or ComputationGraph
     * @throws IOException
     * @throws UnsupportedOperationException
     *
     * TODO: change return type to shared model interface once we have one.
     */
    private static <T> T importModel(String configJson, hdf5.Group weightsGroup, boolean isSequential)
            throws IOException, UnsupportedOperationException {
        /* TODO: once we have a shared API/interface for MultilayerNetwork and ComputationGraph
         * we can just call importModelConfig and infer return type.
         */
        T model = null;
        if (isSequential) {
            MultiLayerConfiguration config = importSequentialModelConfig(configJson);
            MultiLayerNetwork mln = new MultiLayerNetwork(config);
            mln.init();
            model = (T)mln;
        } else {
            ComputationGraphConfiguration config = importFunctionalApiConfig(configJson);
            ComputationGraph cg = new ComputationGraph(config);
            cg.init();
            model = (T)cg;
            throw new UnsupportedOperationException("Keras Functional API models not supported.");
        }

        Map<String, Object> weightsMetadata = extractWeightsMetadataFromConfig(configJson);
        Map<String, Map<String, INDArray>> weights = readWeightsFromHdf5(weightsGroup);
        importWeights(model, weights, weightsMetadata, isSequential);
        return model;
    }

    /**
     * Read Keras model weights from HDF5 Group into nested Map of INDArrays, where outer
     * keys are layer names and inner keys are parameter names.
     *
     * @param weightsGroup  root HDF5 Group storing all Keras weights for single model
     * @return              nested Map from layer names to parameter names to INDArrays
     */
    private static Map<String,Map<String,INDArray>> readWeightsFromHdf5(hdf5.Group weightsGroup) {
        Map<String,Map<String,INDArray>> weightsMap = new HashMap<String,Map<String,INDArray>>();

        List<hdf5.Group> groups = new ArrayList<hdf5.Group>();
        groups.add(weightsGroup);
        while (!groups.isEmpty()) {
            hdf5.Group g = groups.remove(0);
            String groupName = g.getObjName().getString();
            for (int i = 0; i < g.asCommonFG().getNumObjs(); i++) {
                BytePointer objPtr = g.asCommonFG().getObjnameByIdx(i);
                String objName = objPtr.getString();
                int objType = g.asCommonFG().childObjType(objPtr);
                switch (objType) {
                    case H5O_TYPE_DATASET:
                        hdf5.DataSet d = g.asCommonFG().openDataSet(objPtr);
                        hdf5.DataSpace space = d.getSpace();
                        int nbDims = (int)space.getSimpleExtentNdims();
                        long[] dims = new long[nbDims];
                        space.getSimpleExtentDims(dims);
                        float[] weightBuffer = null;
                        FloatPointer fp = null;
                        int j = 0;
                        INDArray weights = null;
                        switch (nbDims) {
                            case 4: /* 2D Convolution weights */
                                weightBuffer = new float[(int)(dims[0]*dims[1]*dims[2]*dims[3])];
                                fp = new FloatPointer(weightBuffer);
                                d.read(fp, new hdf5.DataType(hdf5.PredType.NATIVE_FLOAT()));
                                fp.get(weightBuffer);
                                weights = Nd4j.create((int)dims[0], (int)dims[1], (int)dims[2], (int)dims[3]);
                                j = 0;
                                for (int i1 = 0; i1 < dims[0]; i1++)
                                    for (int i2 = 0; i2 < dims[1]; i2++)
                                        for (int i3 = 0; i3 < dims[2]; i3++)
                                            for (int i4 = 0; i4 < dims[3]; i4++)
                                                weights.putScalar(i1, i2, i3, i4, weightBuffer[j++]);
                                break;
                            case 2: /* Dense and Recurrent weights */
                                weightBuffer = new float[(int)(dims[0]*dims[1])];
                                fp = new FloatPointer(weightBuffer);
                                d.read(fp, new hdf5.DataType(hdf5.PredType.NATIVE_FLOAT()));
                                fp.get(weightBuffer);
                                weights = Nd4j.create((int)dims[0], (int)dims[1]);
                                j = 0;
                                for (int i1 = 0; i1 < dims[0]; i1++)
                                    for (int i2 = 0; i2 < dims[1]; i2++)
                                        weights.putScalar(i1, i2, weightBuffer[j++]);
                                break;
                            case 1: /* bias */
                                weightBuffer = new float[(int)dims[0]];
                                fp = new FloatPointer(weightBuffer);
                                d.read(fp, new hdf5.DataType(hdf5.PredType.NATIVE_FLOAT()));
                                fp.get(weightBuffer);
                                weights = Nd4j.create((int)dims[0]);
                                j = 0;
                                for (int i1 = 0; i1 < dims[0]; i1++)
                                    weights.putScalar(i1, weightBuffer[j++]);
                                break;
                            default:
                                throw new IncompatibleKerasConfigurationException("Cannot import weights with rank " + nbDims);

                        }
                        /* Keras parameter names are typically formatted as [layer name]_[layer no]_[parameter]. For
                         * example, the weight matrix in the first Dense layer will be named "dense_1_W."
                         */
                        String[] tokens = objName.split("_");
                        String layerName = StringUtils.join(Arrays.copyOfRange(tokens, 0, tokens.length-1), "_");
                        String paramName = tokens[tokens.length-1];
                        if (!weightsMap.containsKey(layerName))
                            weightsMap.put(layerName, new HashMap<String, INDArray>());
                        weightsMap.get(layerName).put(paramName, weights);
                        d.close();
                        break;
                    case H5O_TYPE_GROUP:
                    default:
                        groups.add(g.asCommonFG().openGroup(objPtr));
                        break;
                }
            }
            g.close();
        }
        return weightsMap;
    }

    /**
     * Helper function to import weights from nested Map into existing model. Depends critically
     * on matched layer and parameter names. In general this seems to be straightforward for most
     * Keras models and layers, but there may be edge cases.
     *
     * @param model             instantiated DL4J model (MultiLayerNetwork or ComputationGraph)
     * @param weights           nested Map from layer names to parameter names to INDArrays
     * @param weightsMetadata   Map of metadata (e.g., Keras backend)
     * @param isSequential      whether Keras model is Sequential
     * @param <T>
     * @return                  DL4J MultiLayerNetwork or ComputationGraph
     * @throws IncompatibleKerasConfigurationException
     *
     * TODO: change return type to shared model interface once we have one.
     */
    private static <T> T importWeights(T model, Map<String, Map<String, INDArray>> weights,
                                       Map<String, Object> weightsMetadata, boolean isSequential)
            throws IncompatibleKerasConfigurationException {
        /* TODO: how might this break?
         * - mismatch between layer/parameter names?
         */
        String kerasBackend = weightsMetadata.containsKey("keras_backend") ?
                (String) weightsMetadata.get("keras_backend") : "none";
        for (String layerName : weights.keySet()) {
            Layer layer = null;
            if (isSequential)
                layer = ((MultiLayerNetwork)model).getLayer(layerName);
            else
                layer = ((ComputationGraph)model).getLayer(layerName);
            for (String kerasParamName : weights.get(layerName).keySet()) {
                String paramName = null;
                /* TensorFlow backend often appends ":" followed by one
                 * or more digits to parameter names, but this is not
                 * reflected in the model config. We must strip it off.
                 */
                Pattern p = Pattern.compile(":\\d+$");
                Matcher m = p.matcher(kerasParamName);
                if (m.find())
                    paramName = m.replaceFirst("");
                else
                    paramName = kerasParamName;
                INDArray W = weights.get(layerName).get(kerasParamName);
                if (layer instanceof ConvolutionLayer && paramName.equals("W")) {
                    /* Theano and TensorFlow backends store convolutional weights
                     * with a different dimensional ordering than DL4J so we need
                     * to permute them to match.
                     *
                     * DL4J: (# outputs, # channels, # rows, # cols)
                     */
                    if (kerasBackend.equals("tf")) {
                        /* TensorFlow convolutional weights: # rows, # cols, # channels, # outputs */
                        W = W.permute(3, 2, 0, 1);
                    } else if (kerasBackend.equals("th")) {
                        /* Theano convolutional weights: # channels, # rows, # cols, # outputs */
                        W = W.permute(3, 0, 1, 2);
                    } else {
                        throw new IncompatibleKerasConfigurationException("Unknown keras backend " + kerasBackend);
                    }
                    layer.setParam(paramName, W);
                }
                layer.setParam(paramName, W);
            }
        }
        return model;
    }
}


text:
<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>ajaxdemo1_html</title>

<input type="button" id="ajax-btn" value="ajax请求html内容"/>

redpajama_set_name: RedPajamaGithub


text:
<?php
namespace In2code\Powermail\ViewHelpers\Validation;

use In2code\Powermail\Domain\Model\Field;
use In2code\Powermail\Domain\Service\CalculatingCaptchaService;
use In2code\Powermail\Utility\TypoScriptUtility;
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;

/**
 * Get Captcha
 *
 * @package TYPO3
 * @subpackage Fluid
 */
class CaptchaViewHelper extends AbstractViewHelper
{

    /**
     * PersistenceManager
     *
     * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
     * @inject
     */
    protected $persistenceManager;

    /**
     * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
     * @inject
     */
    protected $configurationManager;

    /**
     * Configuration
     *
     * @var array
     */
    protected $settings;

    /**
     * Returns Captcha-Image String
     *
     * @param Field $field
     * @return string image URL
     */
    public function render(Field $field)
    {
        switch (TypoScriptUtility::getCaptchaExtensionFromSettings($this->settings)) {
            case 'captcha':
                $image = ExtensionManagementUtility::siteRelPath('captcha') . 'captcha/captcha.php';
                break;

            default:
                /** @var CalculatingCaptchaService $captchaService */
                $captchaService = $this->objectManager->get(CalculatingCaptchaService::class);
                $image = $captchaService->render($field);
        }
        return $image;
    }

    /**
     * Init
     *
     * @return void
     */
    public function initialize()
    {
        $typoScriptSetup = $this->configurationManager->getConfiguration(
            ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT
        );
        $this->settings = $typoScriptSetup['plugin.']['tx_powermail.']['settings.']['setup.'];
    }
}


text:
<?php

use UliCMS\Models\Content\Advertisement\Banners;
use UliCMS\Models\Content\Advertisement\Banner;
use UliCMS\Models\Content\Category;

class BannersTest extends \PHPUnit\Framework\TestCase
{
    const HTML_TEXT1 = "My first Banner HTML";
    const HTML_TEXT2 = "My second Banner HTML";

    protected function tearDown(): void
    {
        Database::pQuery("DELETE FROM `{prefix}banner` where html in (? , ?)", array(
            self::HTML_TEXT1,
            self::HTML_TEXT2
                ), true);

        Database::query("DELETE FROM `{prefix}categories` where name like 'Testkategorie %'", true);
    }

    public function testGetByCategoryExpectEmptyResult()
    {
        $result = Banners::getByCategory(PHP_INT_MAX);
        $this->assertIsArray($result);
        $this->assertCount(0, $result);
    }

    public function testGetByCategoryExpectArrayOfBanners()
    {
        $category1 = new Category();
        $category1->setName("Testkategorie " . uniqid());
        $category1->save();

        $category2 = new Category();
        $category2->setName("Testkategorie " . uniqid());
        $category2->save();

        $banner1 = new Banner();
        $banner1->setType("html");
        $banner1->setHtml(self::HTML_TEXT1);
        $banner1->setCategoryId($category1->getID());
        $banner1->save();

        $banner2 = new Banner();
        $banner2->setType("html");
        $banner2->setHtml(self::HTML_TEXT1);
        $banner2->setCategoryId($category1->getID());
        $banner2->save();

        $banner3 = new Banner();
        $banner3->setType("gif");
        $banner3->setHtml(self::HTML_TEXT1);
        $banner3->setCategoryId($category2->getID());
        $banner3->save();

        $result1 = Banners::getByCategory($category1->getID());
        $this->assertCount(2, $result1);
        foreach ($result1 as $banner) {
            $this->assertInstanceOf(Banner::class, $banner);
            $this->assertEquals($category1->getID(), $banner->getCategoryId());
        }

        $result2 = Banners::getByCategory($category2->getID());
        $this->assertCount(1, $result2);
        foreach ($result2 as $banner) {
            $this->assertInstanceOf(Banner::class, $banner);
            $this->assertEquals($category2->getID(), $banner->getCategoryId());
        }
    }

    public function testGetByTypeExpectArrayOfBanners()
    {
        $gifBanners = Banners::getByType("gif");

        $this->assertGreaterThanOrEqual(1, $gifBanners);
        foreach ($gifBanners as $banner) {
            $this->assertEquals("gif", $banner->getType());
        }

        $htmlBanners = Banners::getByType("html");
        $this->assertGreaterThanOrEqual(1, $htmlBanners);

        foreach ($htmlBanners as $banner) {
            $this->assertEquals("html", $banner->getType());
        }
    }

    public function testGetByLanguageExpectArrayOfBanners()
    {
        $category1 = new Category();
        $category1->setName("Testkategorie " . uniqid());
        $category1->save();

        $category2 = new Category();
        $category2->setName("Testkategorie " . uniqid());
        $category2->save();

        $banner1 = new Banner();
        $banner1->setType("html");
        $banner1->setHtml(self::HTML_TEXT1);
        $banner1->setCategoryId($category1->getID());
        $banner1->setLanguage("en");
        $banner1->save();

        $banner2 = new Banner();
        $banner2->setType("html");
        $banner2->setHtml(self::HTML_TEXT1);
        $banner2->setCategoryId($category1->getID());
        $banner2->setLanguage("de");
        $banner2->save();

        $germanBanners = Banners::getByLanguage("de");

        $this->assertGreaterThanOrEqual(1, count($germanBanners));
        foreach ($germanBanners as $banner) {
            $this->assertEquals("de", $banner->getLanguage());
        }

        $englishBanners = Banners::getByLanguage("en");
        $this->assertGreaterThanOrEqual(1, count($englishBanners));

        foreach ($englishBanners as $banner) {
            $this->assertEquals("en", $banner->getLanguage());
        }
    }

    public function testGetAll()
    {
        $banners = Banners::getAll();
        $this->assertIsArray($banners);
        $this->assertGreaterThanOrEqual(1, count($banners));
        foreach ($banners as $banner) {
            $this->assertInstanceOf(Banner::class, $banner);
            $this->assertGreaterThanOrEqual(1, $banner->getId());
        }
    }

    public function testGetRandom()
    {
        $_SESSION["language"] = "de";

        for ($i = 1; $i < 5; $i++) {
            $banner = new Banner();
            $banner->setType("html");
            $banner->setHtml(self::HTML_TEXT1);
            $banner->save();
        }

        $banner1 = Banners::getRandom();
        $this->assertInstanceOf(Banner::class, $banner1);

        $banner2 = Banners::getRandom();

        $i = 1;

        do {
            $banner2 = Banners::getRandom();
            $i++;
        } while ($banner1->getId() == $banner2->getId() and
        $i < 20);

        $this->assertNotEquals($banner2->getId(), $banner1->getId());
    }
}


text:
package net.sourceforge.dynamicgmf.diagram.providers;

import java.util.HashMap;
import java.util.Map;

import net.sourceforge.dynamicgmf.diagram.parsers.MessageFormatParser;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.gmf.runtime.common.core.service.AbstractProvider;
import org.eclipse.gmf.runtime.common.core.service.IOperation;
import org.eclipse.gmf.runtime.common.ui.services.parser.GetParserOperation;
import org.eclipse.gmf.runtime.common.ui.services.parser.IParser;
import org.eclipse.gmf.runtime.common.ui.services.parser.IParserProvider;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.ui.services.parser.ParserHintAdapter;

/**
 * @generated
 */
public class EcoreModelParserProvider extends AbstractProvider implements
		IParserProvider {

	private Map<EClass, IParser> parserMap = new HashMap<EClass, IParser>();

	private EAttribute getLabelFeature(EClass eClass) {
	    EAttribute result = null;
	    for (EAttribute eAttribute : eClass.getEAllAttributes())
	    {
	      if (!eAttribute.isMany() && eAttribute.getEType().getInstanceClass() != FeatureMap.Entry.class)
	      {
	        if ("name".equalsIgnoreCase(eAttribute.getName()))
	        {
	          result = eAttribute;
	          break;
	        }
	        else if (result == null)
	        {
	          result = eAttribute;
	        }
	        else if (eAttribute.getEAttributeType().getInstanceClass() == String.class &&
	                 result.getEAttributeType().getInstanceClass() != String.class)
	        {
	          result = eAttribute;
	        }
	      }
	    }
	    return result;
	}

	private IParser createEClassName_Parser(EClass eClass) {
		EAttribute labelFeature = getLabelFeature(eClass);
		if (null == labelFeature) {
			return null;
		}

		EAttribute[] features = new EAttribute[] {
				labelFeature,
		};
		MessageFormatParser parser = new MessageFormatParser(features);
		parser.setViewPattern("{0} :" + eClass.getName());
		parser.setEditorPattern("{0}");
		parser.setEditPattern("{0}");

		parserMap.put(eClass, parser);

		return parser;
	}

	protected IParser getParser(EObject eObject) {
		EClass eClass = eObject.eClass();
		IParser result = parserMap.get(eClass);
		if (null == result) {
			result = createEClassName_Parser(eClass);
		}

		return result;
	}

	/**
	 * @generated NOT
	 */
	public IParser getParser(IAdaptable hint) {
		EObject semanticModel = (EObject) hint.getAdapter(EObject.class);
		if (semanticModel != null) {
			return getParser(semanticModel);
		}
		return null;
	}

	/**
	 * @generated
	 */
	public boolean provides(IOperation operation) {
		if (operation instanceof GetParserOperation) {
			IAdaptable hint = ((GetParserOperation) operation).getHint();
			if (EcoreModelElementTypes.getElement(hint) == null) {
				return false;
			}
			return getParser(hint) != null;
		}
		return false;
	}

	/**
	 * @generated
	 */
	public static class HintAdapter extends ParserHintAdapter {

		/**
		 * @generated
		 */
		private final IElementType elementType;

		/**
		 * @generated
		 */
		public HintAdapter(IElementType type, EObject object, String parserHint) {
			super(object, parserHint);
			assert type != null;
			elementType = type;
		}

		/**
		 * @generated
		 */
		public Object getAdapter(Class adapter) {
			if (IElementType.class.equals(adapter)) {
				return elementType;
			}
			return super.getAdapter(adapter);
		}
	}

}


text:
{% load staticfiles %}
<!DOCTYPE html>

        <title>Thai Food API</title>

        <meta charset="utf-8">
        <meta name="author" content="Ratthasorn Thassana">
        <meta name="keywords" content="">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
          <link rel="stylesheet" href="{% static 'css/main.css' %}">

                    Thaifood API

            {% block content %}
                This is default content
            {% endblock %}


text:
/********************************************************
**
** Theme name: Cubic
** Description: A new base theme for Moodle.
** Creation Date: 05/07/2012
** Author: Bruno Sampaio
** Author URI: http://pessoa.fct.unl.pt/b.sampaio
**
** Customize, edit, poke, prod, and adapt to your needs.
**
*********************************************************/

/* Blocks
-----------------------*/
.block {
	width: 210px;
	padding: 5px;
	margin: 0 auto;
    margin-bottom: 20px;
    border: none;
}

.block .header,
.block .content {
    padding: 5px;
}

.block .title h2 {
    font-size: 1.2em;
	font-weight: bold;
    margin: 0;
	color: black;
}

.block .header .block_action {
	float:right;
	padding: 4px;
	vertical-align:top;
}

.block .block_action img {
	float: right;
	width: 13px;
	height: 13px;
	margin-left: 5px;
}

.block_action .reloadnavigation {
    margin-right: 3px;
}

.block .header .commands {
	margin: 0px;
	padding: 0px;
}

.block h3.main {
    padding: 0.5em 0;
    text-align: left;
    font-size: 1.1em;
}

.block.hidden .content {
	display: none;
}

.block .content .list li.listentry {
	clear:both;
}

.block .content .list .c0 {
	display:inline;
}

.block .content .list .c1 {
	margin-left:5px;
	display:inline;
}

.block .footer {
	margin-top: 5px;
    margin-bottom: 0;
    text-align: center;
}

.block .blockannotation {
	font-size:0.75em;
	margin: -1em 0 1em;
}

.block_navigation .block_tree li {
	overflow:hidden;
}

/** block_list blocks need column stuffs **/
.block.list_block .unlist > li > .column {
	display:-moz-inline-stack;
	display:inline-block;
	zoom:1;
	*display:inline;
}

.ie6 .block.list_block .unlist .column {
	display:inline;
}

.block.beingmoved {
	border-width: 2px;
	border-style: dashed;
}

.blockmovetarget {
	display: block;
	height: 1em;
	margin-bottom: 1em;
	border-width: 2px;
	border-style: dashed;
}

.block-region .invisible {
	opacity: 0.5;
	filter: alpha(opacity=50);
}

.block .block-hider-show,
.block .block-hider-hide {
	cursor:pointer;
}

.block .block-hider-show,
.block.hidden .block-hider-hide {
	display:none;
}

.block.hidden .block-hider-show {
	display:inline;
}

/** Overide for RTL layout **/
.dir-rtl .block .header,
.dir-rtl .block h2.header {text-align:right;}
.dir-rtl .block .header .commands { text-align: right;}

/* Activities
------------------------------*/
.block_activity_modules ul li {
	margin-bottom: 5px;
}

/* Login
------------------------------*/
.block_login .username,
.block_login .password,
.block_login .btn {
	width: 100%;
	margin-bottom: 0.5em;
}

.block_login .loginform input[type=text],
.block_login .loginform input[type=password],
.block_login .loginform input[type=submit] {
	width: 96%;
	margin-left: 2%;
	margin-right: 2%;
}

.block_login .footer {
    text-align: center;
}

/* News
-------------------------------*/
.block_news_items .newlink {
    text-align: center;
    margin-bottom: 5px;
}

.block_news_items .post .head {
    font-style: italic;
    font-size: 0.9em;
    margin-top: 10px;
}

.block_news_items .post .date {
    float: right;
    text-align: right;
}

.block_news_items .post .name {
    float: left;
    color: #555;
}

/* Calendar
-----------------------*/
.block .minicalendar {
	width:100%;
	margin:10px auto;
	border-collapse: separate;
}

.block .minicalendar h3 {
    text-align: center;
    font-size: 1.2em;
}

.maincalendar .calendarmonth th,
.minicalendar th {
    background: none;
}

.minicalendar th abbr {
    border: none;
}

.block .minicalendar th,
.block .minicalendar td {
	padding:2px;
	font-size: 0.85em;
	border-color: transparent;
}

.block .minicalendar td:hover {
	background-color: [[setting:hover_color]];
}

.block .minicalendar td.weekend {
	color:#A00;
}

.block_calendar_upcoming .event {
    font-weight: bold;
}

.block_calendar_upcoming .date {
    font-weight: normal;
    font-size: 0.85em;
    font-style: italic;
    margin-left: 20px;
}

.block .calendar-controls .previous {
	width: 12%;
	float: left;
	text-align: left;
	display: block;
}

.block .calendar-controls .current {
	float:left;
	width:76%;
	text-align: center;
	display: block;
}

.block .calendar-controls .next {
	float: left;
	width: 12%;
	text-align: right;
	display: block;
}

.block .filters table {
	width: 100%;
	padding: 2px;
	border-collapse:separate;
	border-spacing: 2px;
}

.block .filters table td {
	padding: 2px 5px;
}

.block .filters .eventskey img.iconsmall {
	margin: 3px 0px;
}

.block .content h3.eventskey {
	margin-top:0.5em;
	margin-bottom:0;
	margin-left:0.5em;
}

.calendar_filters td,
.minicalendar td,
.minicalendar th {
    padding: 2px;
    font-size: 0.85em;
}

/* Recent Activity
--------------------------------*/
.block_recent_activity .activitydate {
    font-size: 0.9em;
    color: #444;
    margin-bottom: 5px;
}

.block_recent_activity .activityhead {
    font-size: 0.95em;
    margin: 0.5em 0;
}

/* Messages and Online Users
-------------------------------*/
.block_messages .info,
.block_online_users .info {
    text-align: center;
    font-size: 0.85em;
    color: #444;
    margin-bottom: 7px;
}

/* Blog Menu
------------------------------*/
.block_blog_menu .list li {
    font-size: 0.9em;
    margin: 0.25em 0;
}

/* Search Foruns
------------------------------*/
.block_search_forums form #searchform_search,
.block_search_forums form #searchform_button {
	margin: 0;
	margin-bottom: 10px;
}

.block_search_forums form #searchform_search {
	max-width: 55%;
	margin-right: 10px;
}

.block_search_forums form #searchform_button {
	max-width: 40%;
}

/* Online Users
-----------------------*/
.block_online_users .content .list li.listentry {
    height: 35px;
	padding: 3px 1%;
	position: relative;
}

.block_online_users .content .list li.listentry:hover {
    background-color: [[setting:hover_color]];
}

.block_online_users .content .list li.listentry .user {
	margin-right: 18px;
    position:relative;
	clear: both;
}

.block .content .userpicture,
.block_online_users .content .list li.listentry .user .userpicture {
	width: 35px;
	height: 35px;
	margin-right:5px;
}

.block_online_users .content .list li.listentry .user a {
	height: 100%;
	vertical-align: top;
	display: block;
}

.block_online_users .content .list li.listentry .user a:nth-child(1) {
	float: left;
	width: 40px;
}

.block_online_users .content .list li.listentry .user a:nth-child(2) {
	margin-left: 40px;
	position: relative;
}

.block_online_users .content .list li.listentry .message {
	width: 13px;
	height: 13px;
	top: 5px;
	right: 5px;
	position: absolute;
}

.block_online_users .content .list li.listentry .message a {
	width: 13px;
	height: 13px;
	display: block;
}

.block_online_users .content .list li.listentry .message a .iconsmall {
	margin: 0;
	vertical-align: top;
}

/* Settings
-----------------------*/
.block_settings .content .adminsearchform #adminsearchquery {
	width: 95px;
}


text:
.xyz {
    background: blue;
}


text:
title: "Git e a dificuldade em renomear um arquivo"
date: "2016-11-29"
category: ferramental
description: Um problema que acontece de tempos em tempos
background: "#7AAB13"
---

Quem trabalha com Git ou usa ele em casa, provavelmente já teve esse problema.

Quer dizer, existe alguns requisitos pra isso acontecer... Primeiro você não pode usar linux (não me odeie, eu uso linux em casa!) ou seja, isso só costuma acontecer no Mac (Eu uso no trabalho) e no Windows.

O problema é relativamente simples, você renomeia um arquivo, mas você só altera as letras maiúsculas e minúsculas, por exemplo, você pega o seu arquivo _QuitacaoParcial**D**ECompras.java_ e altera para _QuitacaoParcial**d**ECompras.java_

Pronto! Ai você comita e segue a vida. Você não vai ter nenhum problema até que baixe esse projeto novamente ou que outra pessoa de um pull na  máquina dela.

_"Angeliski, se tá bricando né? Porque isso daria problema?"_

O que acontece é que o git por padrão tem uma configuração de case insensitive... Isso quer dizer que pra ele TESTE.java, teste.java, TesTe.java, TEsTe.java **são a mesma coisa.** E isso é um problema, porque quando você altera o nome do arquivo ele não salva essa alteração... O que resulta num problema no próximo pull que for dado, já que você tem um arquivo com o nome errado e acha que ele está certo. Normalmente em projetos Java isso dá problema, por conta da estrutura de pacotes que a linguagem usa (Porque isso se aplica a nome de pastas também).

 _"Mas como eu resolvo isso? Tem algum jeito?"_

A primeira vez que eu me deparei com esse problema eu resolvi da maneira mais porca simples que se possa imaginar. Mudei o nome do arquivo para uma coisa aleatória como A.java, fiz um commit, depois alterei o nome do arquivo para o que eu realmente queria, _QuitacaoParcial**d**ECompras.java. Só que isso sempre me incomodou, parece uma solução extremamente gambiarrenta grosseira. Depois de umas pesquisas, achei na documentação do git a solução:_

> [core.ignoreCase](ftp://www.kernel.org/pub/software/scm/git/docs/git-config.html)
>
> If true, this option enables various workarounds to enable Git to work better on filesystems that are not case sensitive, like FAT. For example, if a directory listing finds "makefile" when Git expects "Makefile", Git will assume it is really the same file, and continue to remember it as "Makefile".
>
> The default is false, except [git-clone(1)](ftp://www.kernel.org/pub/software/scm/git/docs/git-clone.html) or [git-init(1)](ftp://www.kernel.org/pub/software/scm/git/docs/git-init.html) will probe and set core.ignoreCase true if appropriate when the repository is created.

 Nem preciso dizer que eu chorei pulei de alegria não? O que acontece é simples, apesar da propriedade core.ignoreCase ser false por padão o git-clone faz o favor de colocar ela como padrão quando é executado. Isso ai atrapalha tudo! Mas uma vez que a gente sabe qual é o problema é simples de resolver:

```sh
git config --global core.ignorecase false
```

<Signature></Signature>


text:
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_PRIMITIVES_BLOCK_H
#define BITCOIN_PRIMITIVES_BLOCK_H

#include <auxpow.h>
#include <primitives/pureheader.h>
#include <primitives/transaction.h>
#include <serialize.h>
#include <uint256.h>

#include <boost/shared_ptr.hpp>

/** Nodes collect new transactions into a block, hash them into a hash tree,
 * and scan through nonce values to make the block's hash satisfy proof-of-work
 * requirements.  When they solve the proof-of-work, they broadcast the block
 * to everyone and the block is added to the block chain.  The first transaction
 * in the block is a special one that creates a new coin owned by the creator
 * of the block.
 */
class CBlockHeader : public CPureBlockHeader
{
public:

    // auxpow (if this is a merge-minded block)
    boost::shared_ptr<CAuxPow> auxpow;
    bool fAuxPowChecked; // memory only!

    CBlockHeader()
    {
        SetNull();
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        READWRITE(*static_cast<CPureBlockHeader*>(this));

        if (this->IsAuxpow())
        {
            if (ser_action.ForRead())
                auxpow.reset (new CAuxPow());
            assert(auxpow);
            READWRITE(*auxpow);
        } else if (ser_action.ForRead())
            auxpow.reset();
    }

    void SetNull()
    {
        CPureBlockHeader::SetNull();
        auxpow.reset();
        fAuxPowChecked = false;
    }

    /**
     * Set the block's auxpow (or unset it).  This takes care of updating
     * the version accordingly.
     * @param apow Pointer to the auxpow to use or NULL.
     */
    void SetAuxpow (CAuxPow* apow);
};

class CBlock : public CBlockHeader
{
public:
    // network and disk
    std::vector<CTransactionRef> vtx;

    // memory only
    mutable CTxOut txoutMasternode; // masternode payment
    mutable bool fChecked;

    CBlock()
    {
        SetNull();
    }

    CBlock(const CBlockHeader &header)
    {
        SetNull();
        *(static_cast<CBlockHeader*>(this)) = header;
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        READWRITE(*static_cast<CBlockHeader*>(this));
        READWRITE(vtx);
    }

    void SetNull()
    {
        CBlockHeader::SetNull();
        vtx.clear();
        txoutMasternode = CTxOut();
        fChecked = false;
    }

    CBlockHeader GetBlockHeader() const
    {
        CBlockHeader block;
        block.nVersion       = nVersion;
        block.hashPrevBlock  = hashPrevBlock;
        block.hashMerkleRoot = hashMerkleRoot;
        block.hashReserved   = hashReserved;
        block.nTime          = nTime;
        block.nBits          = nBits;
        block.nNonce         = nNonce;
        block.nBigNonce      = nBigNonce;
        block.nSolution      = nSolution;
        block.auxpow         = auxpow;
        return block;
    }

    std::string ToString(bool fHardfork3) const;
};

/** Describes a place in the block chain to another node such that if the
 * other node doesn't have the same branch, it can find a recent common trunk.
 * The further back it is, the further before the fork it may be.
 */
struct CBlockLocator
{
    std::vector<uint256> vHave;

    CBlockLocator() {}

    explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        int nVersion = s.GetVersion();
        if (!(s.GetType() & SER_GETHASH))
            READWRITE(nVersion);
        READWRITE(vHave);
    }

    void SetNull()
    {
        vHave.clear();
    }

    bool IsNull() const
    {
        return vHave.empty();
    }
};

#endif // BITCOIN_PRIMITIVES_BLOCK_H


text:
package com.ofs.ofmc.toolbox;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import java.util.ArrayList;

/**
 * Created by saravana.subramanian on 3/3/17.
 */

public class MetaballView extends View {

    private Paint paint = new Paint();
    private float handle_len_rate = 2f;
    private float radius = 30;
    private final int ITEM_COUNT = 6;
    private final int ITEM_DIVIDER = 60;
    private final float SCALE_RATE = 0.3f;
    private float maxLength;
    private ArrayList<Circle> circlePaths = new ArrayList<>();
    private float mInterpolatedTime;
    private MoveAnimation wa;
    private Circle circle;

    public MetaballView(Context context) {
        super(context);
        init();
    }

    public MetaballView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MetaballView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    private class Circle {
        float[] center;
        float radius;
    }

    public void setPaintMode(int mode) {
        paint.setStyle(mode == 0 ? Paint.Style.STROKE : Paint.Style.FILL);
        invalidate();
    }

    private void init() {
        paint.setColor(0xff4db9ff);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        Circle circlePath = new Circle();
        circlePath.center = new float[]{(radius + ITEM_DIVIDER), radius * (1f + SCALE_RATE)};
        circlePath.radius = radius / 4 * 3;
        circlePaths.add(circlePath);

        for (int i = 1; i < ITEM_COUNT; i++) {
            circlePath = new Circle();
            circlePath.center = new float[]{(radius * 2 + ITEM_DIVIDER) * i, radius * (1f + SCALE_RATE)};
            circlePath.radius = radius;
            circlePaths.add(circlePath);
        }
        maxLength = (radius * 2 + ITEM_DIVIDER) * ITEM_COUNT;
    }

    private float[] getVector(float radians, float length) {
        float x = (float) (Math.cos(radians) * length);
        float y = (float) (Math.sin(radians) * length);
        return new float[]{
                x, y
        };
    }

    private class MoveAnimation extends Animation {

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            mInterpolatedTime = interpolatedTime;
            invalidate();
        }
    }

    /**
     * @param canvas          画布
     * @param j
     * @param i
     * @param v               控制两个圆连接时候长度,间接控制连接线的粗细,该值为1的时候连接线为直线
     * @param handle_len_rate
     * @param maxDistance
     */
    private void metaball(Canvas canvas, int j, int i, float v, float handle_len_rate, float maxDistance) {
        final Circle circle1 = circlePaths.get(i);
        final Circle circle2 = circlePaths.get(j);

        RectF ball1 = new RectF();
        ball1.left = circle1.center[0] - circle1.radius;
        ball1.top = circle1.center[1] - circle1.radius;
        ball1.right = ball1.left + circle1.radius * 2;
        ball1.bottom = ball1.top + circle1.radius * 2;

        RectF ball2 = new RectF();
        ball2.left = circle2.center[0] - circle2.radius;
        ball2.top = circle2.center[1] - circle2.radius;
        ball2.right = ball2.left + circle2.radius * 2;
        ball2.bottom = ball2.top + circle2.radius * 2;

        float[] center1 = new float[]{
                ball1.centerX(),
                ball1.centerY()
        };
        float[] center2 = new float[]{
                ball2.centerX(),
                ball2.centerY()
        };
        float d = getDistance(center1, center2);

        float radius1 = ball1.width() / 2;
        float radius2 = ball2.width() / 2;
        float pi2 = (float) (Math.PI / 2);
        float u1, u2;

        if (d > maxDistance) {
//            canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle1.radius, paint);
            canvas.drawCircle(ball2.centerX(), ball2.centerY(), circle2.radius, paint);
        } else {
            float scale2 = 1 + SCALE_RATE * (1 - d / maxDistance);
            float scale1 = 1 - SCALE_RATE * (1 - d / maxDistance);
            radius2 *= scale2;
//            radius1 *= scale1;
//            canvas.drawCircle(ball1.centerX(), ball1.centerY(), radius1, paint);
            canvas.drawCircle(ball2.centerX(), ball2.centerY(), radius2, paint);

        }

//        Log.d("Metaball_radius", "radius1:" + radius1 + ",radius2:" + radius2);
        if (radius1 == 0 || radius2 == 0) {
            return;
        }

        if (d > maxDistance || d <= Math.abs(radius1 - radius2)) {
            return;
        } else if (d < radius1 + radius2) {
            u1 = (float) Math.acos((radius1 * radius1 + d * d - radius2 * radius2) /
                    (2 * radius1 * d));
            u2 = (float) Math.acos((radius2 * radius2 + d * d - radius1 * radius1) /
                    (2 * radius2 * d));
        } else {
            u1 = 0;
            u2 = 0;
        }
//        Log.d("Metaball", "center2:" + Arrays.toString(center2) + ",center1:" + Arrays.toString(center1));
        float[] centermin = new float[]{center2[0] - center1[0], center2[1] - center1[1]};

        float angle1 = (float) Math.atan2(centermin[1], centermin[0]);
        float angle2 = (float) Math.acos((radius1 - radius2) / d);
        float angle1a = angle1 + u1 + (angle2 - u1) * v;
        float angle1b = angle1 - u1 - (angle2 - u1) * v;
        float angle2a = (float) (angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v);
        float angle2b = (float) (angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v);

//        Log.d("Metaball", "angle1:" + angle1 + ",angle2:" + angle2 + ",angle1a:" + angle1a + ",angle1b:" + angle1b + ",angle2a:" + angle2a + ",angle2b:" + angle2b);

        float[] p1a1 = getVector(angle1a, radius1);
        float[] p1b1 = getVector(angle1b, radius1);
        float[] p2a1 = getVector(angle2a, radius2);
        float[] p2b1 = getVector(angle2b, radius2);

        float[] p1a = new float[]{p1a1[0] + center1[0], p1a1[1] + center1[1]};
        float[] p1b = new float[]{p1b1[0] + center1[0], p1b1[1] + center1[1]};
        float[] p2a = new float[]{p2a1[0] + center2[0], p2a1[1] + center2[1]};
        float[] p2b = new float[]{p2b1[0] + center2[0], p2b1[1] + center2[1]};

//        Log.d("Metaball", "p1a:" + Arrays.toString(p1a) + ",p1b:" + Arrays.toString(p1b) + ",p2a:" + Arrays.toString(p2a) + ",p2b:" + Arrays.toString(p2b));

        float[] p1_p2 = new float[]{p1a[0] - p2a[0], p1a[1] - p2a[1]};

        float totalRadius = (radius1 + radius2);
        float d2 = Math.min(v * handle_len_rate, getLength(p1_p2) / totalRadius);
        d2 *= Math.min(1, d * 2 / (radius1 + radius2));
//        Log.d("Metaball", "d2:" + d2);
        radius1 *= d2;
        radius2 *= d2;

        float[] sp1 = getVector(angle1a - pi2, radius1);
        float[] sp2 = getVector(angle2a + pi2, radius2);
        float[] sp3 = getVector(angle2b - pi2, radius2);
        float[] sp4 = getVector(angle1b + pi2, radius1);
//        Log.d("Metaball", "sp1:" + Arrays.toString(sp1) + ",sp2:" + Arrays.toString(sp2) + ",sp3:" + Arrays.toString(sp3) + ",sp4:" + Arrays.toString(sp4));

        Path path1 = new Path();
        path1.moveTo(p1a[0], p1a[1]);
        path1.cubicTo(p1a[0] + sp1[0], p1a[1] + sp1[1], p2a[0] + sp2[0], p2a[1] + sp2[1], p2a[0], p2a[1]);
        path1.lineTo(p2b[0], p2b[1]);
        path1.cubicTo(p2b[0] + sp3[0], p2b[1] + sp3[1], p1b[0] + sp4[0], p1b[1] + sp4[1], p1b[0], p1b[1]);
        path1.lineTo(p1a[0], p1a[1]);
        path1.close();
        canvas.drawPath(path1, paint);

    }

    private float getLength(float[] b) {
        return (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]);
    }

    private float getDistance(float[] b1, float[] b2) {
        float x = b1[0] - b2[0];
        float y = b1[1] - b2[1];
        float d = x * x + y * y;
        return (float) Math.sqrt(d);
    }

    //测试用
//    @Override
//    public boolean onTouchEvent(MotionEvent event) {
//        switch (event.getAction()) {
//            case MotionEvent.ACTION_DOWN:
//                break;
//            case MotionEvent.ACTION_MOVE:
//                Circle circle = circlePaths.get(0);
//                circle.center[0] = event.getX();
//                circle.center[1] = event.getY();
//                invalidate();
//                break;
//            case MotionEvent.ACTION_UP:
//                break;
//        }
//
//        return true;
//    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        circle = circlePaths.get(0);
        circle.center[0] = maxLength * mInterpolatedTime;

        RectF ball1 = new RectF();
        ball1.left = circle.center[0] - circle.radius;
        ball1.top = circle.center[1] - circle.radius;
        ball1.right = ball1.left + circle.radius * 2;
        ball1.bottom = ball1.top + circle.radius * 2;
        canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle.radius, paint);

        for (int i = 1, l = circlePaths.size(); i < l; i++) {
            metaball(canvas, i, 0, 0.6f, handle_len_rate, radius * 4f);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(resolveSizeAndState((int) (ITEM_COUNT * (radius * 2 + ITEM_DIVIDER)), widthMeasureSpec, 0),
                resolveSizeAndState((int) (2 * radius * 1.4f), heightMeasureSpec, 0));
    }

    private void stopAnimation() {
        this.clearAnimation();
        postInvalidate();
    }

    private void startAnimation() {
        wa = new MoveAnimation();
        wa.setDuration(2500);
        wa.setInterpolator(new AccelerateDecelerateInterpolator());
        wa.setRepeatCount(Animation.INFINITE);
        wa.setRepeatMode(Animation.REVERSE);
        startAnimation(wa);
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);

        if (visibility == GONE || visibility == INVISIBLE) {
            stopAnimation();
        } else {
            startAnimation();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startAnimation();
    }

    @Override
    protected void onDetachedFromWindow() {
        stopAnimation();
        super.onDetachedFromWindow();
    }
}


text:
package thehambone.blackopsterminalemulator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import thehambone.blackopsterminalemulator.filesystem.FileSystem;

/**
 * A {@code Server} is a system that hosts files and and contains a set of users
 * what have access to those files.
 *

 * Created on Nov 28, 2015.
 *
 * @author Wes Hampson
 */
public class Server
{
    private final String name;
    private final String loginMessage;
    private final List<UserAccount> users;

    private FileSystem fileSystem;

    /**
     * Creates a new {@code Server}.
     *
     * @param name the name of the server
     * @param loginMessage the message to be displayed when a user attempts to
     *                     log in
     */
    public Server(String name, String loginMessage)
    {
        this.name = name;
        this.loginMessage = loginMessage;

        this.users = new ArrayList<>();
    }

    /**
     * Gets the name of this server.
     *
     * @return the server name
     */
    public String getName()
    {
        return name;
    }

    /**
     * Gets the {@code FileSystem} object containing the files and directories
     * on this system.
     *
     * @return the {@code FileSystem} object associated with this system
     */
    public FileSystem getFileSystem()
    {
        return fileSystem;
    }

    /**
     *
     * @param fileSystem a {@code FileSystem} object containing containing the
     *                   directories and files for the system
     */
    public void setFileSystem(FileSystem fileSystem)
    {
        this.fileSystem = fileSystem;
    }

    /**
     * Adds a user account to this server.
     *
     * @param u the user account to add
     */
    public void addUser(UserAccount u)
    {
        users.add(u);
    }

    /**
     * Gets a user account on this server by its username.
     *
     * @param username the username of the user account to search for
     * @return the user account with the matching username, {@code null} if the
     *         account is not found
     */
    public UserAccount getUser(String username)
    {
        UserAccount user = null;

        for (UserAccount u : users) {
            if (u.getUsername().equalsIgnoreCase(username)) {
                user = u;
                break;
            }
        }

        return user;
    }

    /**
     * Returns a list containing all users that have accounts on this server.
     *
     * @return a list of users on this server
     */
    public List<UserAccount> getUsers()
    {
        return Collections.unmodifiableList(users);
    }

    /**
     * Invokes the user login process for this server.
     *

     * The login process is as follows:
     *     1) The user is prompted to enter their username.
     *     2) The user is prompted to enter their password.
     *     3) The username and password are validated. If validation is
     *        successful, a new {@code LoginShell} is returned starting in the
     *        user's home directory.
     *
     * @return a login shell for the user if the login attempt was successful,
     *         {@code null} if the login attempt was not successful
     */
    public LoginShell login()
    {
        // Show login message
        if (!loginMessage.isEmpty()) {
            Terminal.println(loginMessage);
        }

        // Prompt for username
        Terminal.print("USER:");
        String username = Terminal.readLine();

        // Prompt for password
        Terminal.print("PASSWORD:");
        String password = Terminal.readLine('*');

        // Validate username and password
        // If the user's homedir is unlisted, don't validate
        LoginShell shell = null;
        UserAccount user = getUser(username);
        if (user == null || !user.getPassword().equalsIgnoreCase(password)
                || user.getHomeDirectory().isUnlisted()) {
            Terminal.println("Invalid Password");
        } else {
            shell = new LoginShell(this, user);
        }

        return shell;
    }
}