text:
package com.owera.xaps.core.util;

public class UnitJobResult {

	private boolean confirmedFailure = false;
	private boolean unconfirmedFailure = false;

	public UnitJobResult() {
	}

	/* The method sets the confirmed flag, but also
	 * return -1, 0 or 1, depending upon these conditions:
	 * 1: change to confirmedFailure
	 * 0: no change
	 * -1: change to !confirmedFailure
	 */
	public int setConfirmed(int confirmed) {
		int result = 0;
		if (confirmed > 0) {
			if (!confirmedFailure)
				result = 1;
			confirmedFailure = true;
		} else {
			if (confirmedFailure)
				result = -1;
			confirmedFailure = false;
		}
		return result;
	}

	public int setUnconfirmed(int unconfirmed) {
		int result = 0;
		if (unconfirmed > 0) {
			if (!unconfirmedFailure)
				result = 1;
			unconfirmedFailure = true;
		} else {
			if (unconfirmedFailure)
				result = -1;
			unconfirmedFailure = false;
		}
		return result;
	}

	public boolean isConfirmedFailure() {
		return confirmedFailure;
	}

	public boolean isUnconfirmedFailure() {
		return unconfirmedFailure;
	}
}


text:
package org.apache.cloudstack.storage.test;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

import javax.inject.Inject;

import org.mockito.Matchers;
import org.mockito.Mockito;
import org.springframework.test.context.ContextConfiguration;
import org.testng.Assert;
import org.testng.annotations.Test;

import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.storage.RemoteHostEndPoint;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;

import com.cloud.agent.AgentManager;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Cluster.ClusterType;
import com.cloud.org.Managed.ManagedState;
import com.cloud.resource.ResourceState;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.utils.component.ComponentContext;

@ContextConfiguration(locations = {"classpath:/storageContext.xml"})
public class VolumeServiceTest extends CloudStackTestNGBase {
    // @Inject
    // ImageDataStoreProviderManager imageProviderMgr;
    @Inject
    TemplateService imageService;
    @Inject
    VolumeService volumeService;
    @Inject
    VMTemplateDao imageDataDao;
    @Inject
    VolumeDao volumeDao;
    @Inject
    HostDao hostDao;
    @Inject
    HostPodDao podDao;
    @Inject
    ClusterDao clusterDao;
    @Inject
    DataCenterDao dcDao;
    @Inject
    PrimaryDataStoreDao primaryStoreDao;
    @Inject
    DataStoreProviderManager dataStoreProviderMgr;
    @Inject
    AgentManager agentMgr;
    @Inject
    EndPointSelector selector;
    @Inject
    TemplateDataFactory imageDataFactory;
    @Inject
    VolumeDataFactory volumeFactory;
    @Inject
    ImageStoreDao imageStoreDao;
    ImageStoreVO imageStore;
    Long dcId;
    Long clusterId;
    Long podId;
    HostVO host;
    String primaryName = "my primary data store";
    DataStore primaryStore;

    @Test(priority = -1)
    public void setUp() {
        ComponentContext.initComponentsLifeCycle();

        host = hostDao.findByGuid(this.getHostGuid());
        if (host != null) {
            dcId = host.getDataCenterId();
            clusterId = host.getClusterId();
            podId = host.getPodId();
            return;
        }
        // create data center
        DataCenterVO dc =
            new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true,
                true, null, null);
        dc = dcDao.persist(dc);
        dcId = dc.getId();
        // create pod

        HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test");
        pod = podDao.persist(pod);
        podId = pod.getId();
        // create xenserver cluster
        ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
        cluster.setHypervisorType(HypervisorType.XenServer.toString());
        cluster.setClusterType(ClusterType.CloudManaged);
        cluster.setManagedState(ManagedState.Managed);
        cluster = clusterDao.persist(cluster);
        clusterId = cluster.getId();
        // create xenserver host

        host = new HostVO(this.getHostGuid());
        host.setName("devcloud xenserver host");
        host.setType(Host.Type.Routing);
        host.setPrivateIpAddress(this.getHostIp());
        host.setDataCenterId(dc.getId());
        host.setVersion("6.0.1");
        host.setAvailable(true);
        host.setSetup(true);
        host.setPodId(podId);
        host.setLastPinged(0);
        host.setResourceState(ResourceState.Enabled);
        host.setHypervisorType(HypervisorType.XenServer);
        host.setClusterId(cluster.getId());

        host = hostDao.persist(host);

        imageStore = new ImageStoreVO();
        imageStore.setName("test");
        imageStore.setDataCenterId(dcId);
        imageStore.setProviderName("CloudStack ImageStore Provider");
        imageStore.setRole(DataStoreRole.Image);
        imageStore.setUrl(this.getSecondaryStorage());
        imageStore.setUuid(UUID.randomUUID().toString());
        imageStore = imageStoreDao.persist(imageStore);

    }

    @Override
    protected void injectMockito() {
        if (host == null) {
            return;
        }
        List<HostVO> results = new ArrayList<HostVO>();
        results.add(host);
        Mockito.when(hostDao.listAll()).thenReturn(results);
        Mockito.when(hostDao.findById(Matchers.anyLong())).thenReturn(host);
        Mockito.when(hostDao.findHypervisorHostInCluster(Matchers.anyLong())).thenReturn(results);
        List<EndPoint> eps = new ArrayList<EndPoint>();
        eps.add(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
        Mockito.when(selector.selectAll(Matchers.any(DataStore.class))).thenReturn(eps);
        Mockito.when(selector.select(Matchers.any(DataObject.class))).thenReturn(eps.get(0));
        Mockito.when(selector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))).thenReturn(eps.get(0));
    }

    private VMTemplateVO createImageData() {
        VMTemplateVO image = new VMTemplateVO();
        image.setTemplateType(TemplateType.USER);
        image.setUrl(this.getTemplateUrl());
        image.setUniqueName(UUID.randomUUID().toString());
        image.setName(UUID.randomUUID().toString());
        image.setPublicTemplate(true);
        image.setFeatured(true);
        image.setRequiresHvm(true);
        image.setBits(64);
        image.setFormat(Storage.ImageFormat.VHD);
        image.setEnablePassword(true);
        image.setEnableSshKey(true);
        image.setGuestOSId(1);
        image.setBootable(true);
        image.setPrepopulate(true);
        image.setCrossZones(true);
        image.setExtractable(true);

        // image.setImageDataStoreId(storeId);
        image = imageDataDao.persist(image);

        return image;
    }

    private TemplateInfo createTemplate() {
        try {
            DataStore store = createImageStore();
            VMTemplateVO image = createImageData();
            TemplateInfo template = imageDataFactory.getTemplate(image.getId(), store);
            // AsyncCallFuture<TemplateApiResult> future =
            // imageService.createTemplateAsync(template, store);
            // future.get();
            template = imageDataFactory.getTemplate(image.getId(), store);
            /*
             * imageProviderMgr.configure("image Provider", new HashMap<String,
             * Object>()); VMTemplateVO image = createImageData();
             * ImageDataStoreProvider defaultProvider =
             * imageProviderMgr.getProvider("DefaultProvider");
             * ImageDataStoreLifeCycle lifeCycle =
             * defaultProvider.getLifeCycle(); ImageDataStore store =
             * lifeCycle.registerDataStore("defaultHttpStore", new
             * HashMap<String, String>());
             * imageService.registerTemplate(image.getId(),
             * store.getImageDataStoreId()); TemplateEntity te =
             * imageService.getTemplateEntity(image.getId()); return te;
             */
            return template;
        } catch (Exception e) {
            Assert.fail("failed", e);
            return null;
        }
    }

    // @Test
    public void createTemplateTest() {
        createTemplate();
    }

    @Test
    public void testCreatePrimaryStorage() {
        DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample primary data store provider");
        Map<String, Object> params = new HashMap<String, Object>();
        URI uri = null;
        try {
            uri = new URI(this.getPrimaryStorageUrl());
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        params.put("url", this.getPrimaryStorageUrl());
        params.put("server", uri.getHost());
        params.put("path", uri.getPath());
        params.put("protocol", StoragePoolType.NetworkFilesystem);
        params.put("dcId", dcId.toString());
        params.put("clusterId", clusterId.toString());
        params.put("name", this.primaryName);
        params.put("port", "1");
        params.put("roles", DataStoreRole.Primary.toString());
        params.put("uuid", UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString());
        params.put("providerName", String.valueOf(provider.getName()));

        DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
        this.primaryStore = lifeCycle.initialize(params);
        ClusterScope scope = new ClusterScope(clusterId, podId, dcId);
        lifeCycle.attachCluster(this.primaryStore, scope);
    }

    private DataStore createImageStore() {
        DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample image data store provider");
        Map<String, Object> params = new HashMap<String, Object>();
        String name = UUID.randomUUID().toString();
        params.put("name", name);
        params.put("uuid", name);
        params.put("protocol", "http");
        params.put("scope", ScopeType.GLOBAL.toString());
        params.put("providerName", name);
        DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
        DataStore store = lifeCycle.initialize(params);
        return store;
    }

    // @Test
    public void testcreateImageStore() {
        createImageStore();
    }

    public DataStore createPrimaryDataStore() {
        try {
            DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample primary data store provider");
            Map<String, Object> params = new HashMap<String, Object>();
            URI uri = new URI(this.getPrimaryStorageUrl());
            params.put("url", this.getPrimaryStorageUrl());
            params.put("server", uri.getHost());
            params.put("path", uri.getPath());
            params.put("protocol", Storage.StoragePoolType.NetworkFilesystem);
            params.put("dcId", dcId.toString());
            params.put("clusterId", clusterId.toString());
            params.put("name", this.primaryName);
            params.put("port", "1");
            params.put("roles", DataStoreRole.Primary.toString());
            params.put("uuid", UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString());
            params.put("providerName", String.valueOf(provider.getName()));

            DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
            DataStore store = lifeCycle.initialize(params);
            ClusterScope scope = new ClusterScope(clusterId, podId, dcId);
            lifeCycle.attachCluster(store, scope);

            /*
             * PrimaryDataStoreProvider provider =
             * primaryDataStoreProviderMgr.getDataStoreProvider
             * ("sample primary data store provider");
             * primaryDataStoreProviderMgr.configure("primary data store mgr",
             * new HashMap<String, Object>());
             *
             * List<PrimaryDataStoreVO> ds =
             * primaryStoreDao.findPoolByName(this.primaryName); if (ds.size()
             * >= 1) { PrimaryDataStoreVO store = ds.get(0); if
             * (store.getRemoved() == null) { return
             * provider.getDataStore(store.getId()); } }
             *
             *
             * Map<String, String> params = new HashMap<String, String>();
             * params.put("url", this.getPrimaryStorageUrl());
             * params.put("dcId", dcId.toString()); params.put("clusterId",
             * clusterId.toString()); params.put("name", this.primaryName);
             * PrimaryDataStoreInfo primaryDataStoreInfo =
             * provider.registerDataStore(params); PrimaryDataStoreLifeCycle lc
             * = primaryDataStoreInfo.getLifeCycle(); ClusterScope scope = new
             * ClusterScope(clusterId, podId, dcId); lc.attachCluster(scope);
             * return primaryDataStoreInfo;
             */
            return store;
        } catch (Exception e) {
            return null;
        }
    }

    private VolumeVO createVolume(Long templateId, long dataStoreId) {
        VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
        volume.setPoolId(dataStoreId);
        volume = volumeDao.persist(volume);
        return volume;
    }

    @Test(priority = 2)
    public void createVolumeFromTemplate() {
        DataStore primaryStore = this.primaryStore;
        TemplateInfo te = createTemplate();
        VolumeVO volume = createVolume(te.getId(), primaryStore.getId());
        VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore);
        // ve.createVolumeFromTemplate(primaryStore.getId(), new VHD(), te);
        AsyncCallFuture<VolumeApiResult> future = volumeService.createVolumeFromTemplateAsync(vol, primaryStore.getId(), te);
        try {
            future.get();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // @Test(priority=3)
    public void createDataDisk() {
        DataStore primaryStore = this.primaryStore;
        VolumeVO volume = createVolume(null, primaryStore.getId());
        VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore);
        AsyncCallFuture<VolumeApiResult> future = volumeService.createVolumeAsync(vol, primaryStore);
        try {
            future.get();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // @Test(priority=3)
    public void createAndDeleteDataDisk() {
        DataStore primaryStore = this.primaryStore;
        VolumeVO volume = createVolume(null, primaryStore.getId());
        VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore);
        AsyncCallFuture<VolumeApiResult> future = volumeService.createVolumeAsync(vol, primaryStore);
        try {
            future.get();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // delete the volume
        vol = volumeFactory.getVolume(volume.getId(), primaryStore);
        future = volumeService.expungeVolumeAsync(vol);
        try {
            future.get();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // @Test(priority=3)
    public void tearDown() {
        List<StoragePoolVO> ds = primaryStoreDao.findPoolByName(this.primaryName);
        for (int i = 0; i < ds.size(); i++) {
            StoragePoolVO store = ds.get(i);
            store.setUuid(null);
            primaryStoreDao.remove(ds.get(i).getId());
            primaryStoreDao.expunge(ds.get(i).getId());
        }
    }

    // @Test
    // @Test
    public void test1() {
        /*
         * System.out.println(VolumeTypeHelper.getType("Root"));
         * System.out.println(VolumeDiskTypeHelper.getDiskType("vmdk"));
         * System.out.println(ImageFormatHelper.getFormat("ova"));
         * AssertJUnit.assertFalse(new VMDK().equals(new VHD())); VMDK vmdk =
         * new VMDK(); AssertJUnit.assertTrue(vmdk.equals(vmdk)); VMDK newvmdk =
         * new VMDK(); AssertJUnit.assertTrue(vmdk.equals(newvmdk));
         *
         * ImageFormat ova = new OVA(); ImageFormat iso = new ISO();
         * AssertJUnit.assertTrue(ova.equals(new OVA()));
         * AssertJUnit.assertFalse(ova.equals(iso));
         * AssertJUnit.assertTrue(ImageFormatHelper.getFormat("test").equals(new
         * Unknown()));
         *
         * VolumeDiskType qcow2 = new QCOW2(); ImageFormat qcow2format = new
         * org.apache.cloudstack.storage.image.format.QCOW2();
         * AssertJUnit.assertFalse(qcow2.equals(qcow2format));
         */
    }

}

redpajama_set_name: RedPajamaGithub


text:
package com.ifeng.vdn.ip.repository.service.impl;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.ifeng.vdn.ip.repository.bean.ali.AliIPBean;
import com.ifeng.vdn.ip.repository.service.BatchIPAddressChecker;
import com.ifeng.vdn.ip.repository.service.impl.AliBatchIPAddressChecker;
import com.ifeng.vdn.ip.repository.service.impl.AliIPAddressChecker;

/**
 * @version 0.1
 *
 * @author Hefei Li
 *
 * @since  Apr 15, 2015
 */
public class AliBatchIPAddressCheckerTest {
	private static final Logger log = LoggerFactory.getLogger(AliIPAddressChecker.class);

	@Test
	public void check() throws JsonParseException, JsonMappingException, IOException {
		BatchIPAddressChecker<AliIPBean> checker = new AliBatchIPAddressChecker();

		//IPAddress ip = checker.ipcheck("61.236.238.98");
		List<String> ips = new ArrayList<String>();
		ips.add("61.236.238.98");
		ips.add("61.155.167.220");
		ips.add("118.122.88.132");
		ips.add("123.151.185.103");

		List<AliIPBean> list = checker.check(ips);

		for(AliIPBean ip : list){
			log.info(ip.getIpString());
		}
	}

	@Test
	public void wrap() {
		Workbook wb = null;
		try {
			BatchIPAddressChecker<AliIPBean> checker = new AliBatchIPAddressChecker();

			wb = WorkbookFactory.create(new FileInputStream("src/test/resources/data/ip_18.xlsx"));
			Sheet sheet = wb.getSheetAt(0);

			int totalRows = sheet.getPhysicalNumberOfRows();
			Cell ipCell = null;
			Cell locCell = null;

			List<String> ips = new ArrayList<String>();

			for (int i = 1; i < totalRows; i++) {
				Row row = sheet.getRow(i);
				ipCell = row.getCell(1);

				ips.add(ipCell.getStringCellValue());
			}

			List<AliIPBean> locations = checker.check(ips);
			String location = "";

			for (int i = 1; i < totalRows; i++) {
				Row row = sheet.getRow(i);
				locCell = row.getCell(3);

				try {
					location = locations.get(i).getIpString();
				} catch (Exception e) {
					location = "ERROR";
				}

				locCell.setCellValue(location);
			}

			/*if(location.length() == (totalRows - 1)){

			}else {
				log.error("Batch executed error");
				throw new RuntimeException("Batch executed error. Some one IP location not be checked.");
			}*/

			wb.write(new FileOutputStream("src/test/resources/data/ip_18_Alibaba.xlsx"));

		} catch (InvalidFormatException | IOException e) {
			e.printStackTrace();
		} finally {
			if(wb != null)
				try {
					wb.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

	}
}


text:
<!doctype html>

    <meta charset="utf-8">

    <title>ActiveAdmin</title>

    <meta name="description" content="A framework for easily creating beautiful presentations using HTML">
    <meta name="author" content="Hakim El Hattab">

    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />

    <link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic,700italic' rel='stylesheet' type='text/css'>

    <link rel="stylesheet" href="css/main.css">
    <link rel="stylesheet" href="css/theme/activeadmin.css" id="theme">

    <link rel="stylesheet" href="lib/css/github.css">

ActiveAdmin

An administration framework for Ruby on Rails

The Problem

class PostsController < ApplicationController
              def update
                @post = Post.find(params[:id])
                @post.update_attributes(params[:post])
              end
            end

            class PagesController < ApplicationController
              def update
                @page = Page.find(params[:id])
                @page.update_attributes(params[:page])
              end
            end

The Problem

  <%= form_for(@post) do |f| %>
                <%= f.text_field :title %>
                <%= f.text_area :body %>

                <%= f.submit %>
              <% end %>

              <%= form_for(@page) do |f| %>
                <%= f.text_field :title %>
                <%= f.text_area :body %>

                <%= f.submit %>
              <% end %>

The Solution

ActiveAdmin.register Post do
          end

          ActiveAdmin.register Page do
          end

It's Pretty

Get Started

Add to Gemfile

gem 'activeadmin'

Run in CLI

rails generate active_admin:install
          rails generate active_admin:resource [resource]

Domain Specific Language

Index Views

index do
              column :title
              column :author
              default_actions
            end

            index do
              column :title
              if can? :manage, Post
                column :some_secret_data
              end
            end

Show Views

show do
              h3 post.title
              div do
                markdown post.body
              end

              panel "Comments" do
                table_for(workshop.comments) do
                  column :name
                  column :email
                end
              end
            end

Form Definitions

form do |f|
              f.inputs "Post Details" do
                f.input :title
                f.input :author, :as => :select, :collection => ["Tristan O'Neil"]
                f.input :created_at, :ampm => true
                f.input :body
              end

              f.buttons
            end

Controller Definitions

controller do
              def update
                # override default update action behavior.
              end
            end

Demo Time

        ◄
        ►
        ▲
        ▼


text:
package com.google.code.twig.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.regex.Pattern;

import com.google.code.twig.configuration.DefaultConfiguration;
import com.google.code.twig.util.generic.Generics;
import com.vercer.generics.ParameterizedTypeImpl;

public class AnnotationConfiguration extends DefaultConfiguration
{
	public void register(Class<?> type)
	{
		Class<?> tempType = type;
		do
		{
			Entity annotation = type.getAnnotation(Entity.class);
			if (annotation != null && !annotation.kind().equals(""))
			{
				registerTypeName(type, annotation.kind());
			}
			if (!polymorphic(type)) break;

			tempType = tempType.getSuperclass();
		}
		while (tempType != Object.class);
	}

	@Override
	public boolean polymorphic(Class<?> instance)
	{
		Entity annotation = instance.getClass().getAnnotation(Entity.class);
		if (annotation != null)
		{
			return annotation.polymorphic();
		}
		return false;
	}

	@Override
	public boolean key(Field field)
	{
		return field.isAnnotationPresent(GaeKey.class);
	}

	public boolean child(Field field)
	{
		return field.isAnnotationPresent(Child.class);
	}

	public boolean parent(Field field)
	{
		return field.isAnnotationPresent(Parent.class);
	}

	public boolean embed(Field field)
	{
		Embedded annotation = field.getAnnotation(Embedded.class);
		if (annotation == null)
		{
			annotation = field.getType().getAnnotation(Embedded.class);
		}

		if (annotation != null)
		{
			return annotation.value();
		}
		else
		{
			Embed oldAnnotation = field.getAnnotation(Embed.class);
			if (oldAnnotation == null)
			{
				oldAnnotation = field.getType().getAnnotation(Embed.class);
			}

			if (oldAnnotation != null)
			{
				return oldAnnotation.value();
			}
			else
			{
				return false;
			}
		}
	}

	@Override
	public String[] denormalise(Field field)
	{
		Denormalise annotation = field.getAnnotation(Denormalise.class);
		if (annotation == null)
		{
			return null;
		}
		else
		{
			return annotation.value();
		}
	}

	private static final Pattern innerClassNamePattern = Pattern.compile(".*this\\$[0-9]+");

	public boolean store(Field field)
	{
		Store annotation = field.getAnnotation(Store.class);
		if (annotation != null)
		{
			return annotation.value();
		}
		else
		{
			int modifiers = field.getModifiers();
			if (Modifier.isTransient(modifiers))
			{
				return false;
			}

			if (Modifier.isFinal(modifiers))
			{
				String name = field.getName();
				if (innerClassNamePattern.matcher(name).matches())
				{
					throw new IllegalStateException("Inner class " + field.getDeclaringClass()
							+ " must be declared static");
				}
				else
				{
//					throw new IllegalStateException("Final field " + field + " cannot be stored");
				}
			}

			return true;
		}
	}

	@Override
	public int serializationThreshold(Field field)
	{
		Store annotation = field.getAnnotation(Store.class);
		if (annotation != null)
		{
			return annotation.serializeThreshold();
		}
		else
		{
			return -1;
		}
	}

	public Boolean index(Field field)
	{
		Index annotation = field.getDeclaringClass().getAnnotation(Index.class);
		if (field.getAnnotation(Index.class) != null)
		{
			annotation = field.getAnnotation(Index.class);
		}

		if (annotation != null)
		{
			return annotation.value();
		}
		else
		{
			return null;
		}
	}

	@SuppressWarnings("deprecation")
	public boolean id(Field field)
	{
		return field.isAnnotationPresent(Key.class) || field.isAnnotationPresent(Id.class);
	}

	@Override
	public java.lang.reflect.Type typeOf(Field field)
	{
		Type annotation = field.getAnnotation(Type.class);
		if (annotation == null)
		{
			return super.typeOf(field);
		}
		else
		{
			if (annotation.parameters().length == 0)
			{
				return annotation.value();
			}
			else
			{
				return new ParameterizedTypeImpl(annotation.value(), annotation.parameters(), null);
			}
		}
	}

	// @Override
	// protected String typeToName(java.lang.reflect.Type type)
	// {
	// Class<?> erased = GenericTypeReflector.erase(type);
	// Entity annotation = erased.getAnnotation(Entity.class);
	// if (annotation != null && annotation.kind().length() > 0)
	// {
	// return annotation.kind();
	// }
	//
	// return super.typeToName(type);
	// }

	public boolean polymorphic(Field field)
	{
		Embedded annotation = field.getAnnotation(Embedded.class);
		if (annotation == null)
		{
			annotation = field.getType().getAnnotation(Embedded.class);
		}

		if (annotation != null)
		{
			return annotation.polymorphic();
		}
		else
		{
			// final classes cannot be polymorphic - all others can
			return !Modifier.isFinal(field.getType().getModifiers());
		}
	}

	public boolean entity(Field field)
	{
		return field.isAnnotationPresent(Parent.class) ||
				field.isAnnotationPresent(Child.class) ||
				field.isAnnotationPresent(Denormalise.class) ||
				field.isAnnotationPresent(Independent.class);
	}

	public int activationDepth(Field field, Integer depth)
	{
		if (field.isAnnotationPresent(Activate.class))
		{
			return field.getAnnotation(Activate.class).value();
		}
		return depth;
	}

	@Override
	protected int version(java.lang.reflect.Type type)
	{
		Class<?> clazz = Generics.erase(type);
		if (clazz.isAnnotationPresent(Entity.class))
		{
			return clazz.getAnnotation(Entity.class).version();
		}
		else
		{
			return super.version(type);
		}
	}

	@Override
	public long allocateIdsFor(java.lang.reflect.Type type)
	{
		Class<?> clazz = Generics.erase(type);
		if (clazz.isAnnotationPresent(Entity.class))
		{
			return clazz.getAnnotation(Entity.class).allocateIdsBy();
		}
		else
		{
			return 0;
		}
	}

	@Override
	public String name(Field field)
	{
		Store annotation = field.getAnnotation(Store.class);
		if (annotation != null && !annotation.name().isEmpty())
		{
			return annotation.name();
		}
		else
		{
			return super.name(field);
		}
	}
}


text:
require 'erb'
#require 'pry'

#start the measure
class ZoneReportCopy < OpenStudio::Ruleset::ReportingUserScript

  #define the name that a user will see, this method may be deprecated as
  #the display name in PAT comes from the name field in measure.xml
  def name
    return "Zone Report Copy"
  end

  #define the arguments that the user will input
  def arguments()
    args = OpenStudio::Ruleset::OSArgumentVector.new
    return args
  end #end the arguments method

  # return a vector of IdfObject's to request EnergyPlus objects needed by the run method
  def energyPlusOutputRequests(runner, user_arguments)
    super(runner, user_arguments)

    result = OpenStudio::IdfObjectVector.new

    # use the built-in error checking
    if !runner.validateUserArguments(arguments(), user_arguments)
      return result
    end

    request = OpenStudio::IdfObject.load("Output:Table:SummaryReports,AllSummaryAndSizingPeriod;").get
    result << request

    return result
  end

  # Method to make class names nicer (remove OS and _)
  def niceClassName(class_name)
    class_name = class_name.gsub('OS_','')
    class_name = class_name.gsub('_',' ')
    return class_name
  end

  # Convert a value from the view TabularDataWithStrings from the unit represented there to the given unit.
  # We make a bunch of special cases for unit aliases used by EnergyPlus which are not in the default
  # list of OpenStudio conversions
  # We also special case a few conversions for unitless 'units' so that our final display makes more sense to the user.
  # When the property is not present (for instance, cooled beams don't have properties in the sql file under 1.5)
  # this method will return "-" as a placeholder.
  def eplus_to_openstudio(unitstr)
    unitstr.gsub("m3", "m^3").gsub("pa", "Pa").gsub("m2", "m^2").gsub(" per ", "/")
  end

  def convert_prop(property, final_units)
    return ["-", "-"] unless property

    return [property[0].to_f.round(2), ""] if final_units.empty?
    return [(property[0].to_f * 100).round(2), "%"] if final_units == "%"
    return [property[0].to_f.round(2), "COP"] if final_units == "COP"

    initial_units = eplus_to_openstudio(property[1])
    converted = OpenStudio::convert(property[0].to_f, initial_units, final_units)
    if converted.empty?
      "Could not convert from #{initial_units} to #{final_units}"
    else
      final_units = final_units.gsub("inH_{2}O", "in. w.c.")
      [converted.get.round(2), final_units]
    end
  end

  def properties_for_cooling_coil(e, props, parent)
    autosized = case e.iddObjectType
                  when OpenStudio::Model::CoilCoolingDXSingleSpeed.iddObjectType
                    coil = e.to_CoilCoolingDXSingleSpeed.get
                    (coil.isRatedTotalCoolingCapacityAutosized and coil.isRatedSensibleHeatRatioAutosized and coil.isRatedAirFlowRateAutosized) ? "Yes" : "No"
                  when OpenStudio::Model::CoilCoolingWater.iddObjectType
                    coil = e.to_CoilCoolingWater.get
                    (coil.isDesignWaterFlowRateAutosized and coil.isDesignAirFlowRateAutosized and coil.isDesignInletWaterTemperatureAutosized) ? "Yes" : "No"
                  when OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.iddObjectType
                    coil = e.to_CoilCoolingWaterToAirHeatPumpEquationFit.get
                    (coil.isRatedTotalCoolingCapacityAutosized and coil.isRatedSensibleHeatRatioAutosized and coil.isRatedAirFlowRateAutosized) ? "Yes" : "No"
                  else
                    "?"
                end

    coolingcap = convert_prop(props["Nominal Total Capacity"], "kBtu/hr")
    coolingeff = convert_prop(props["Nominal Efficiency"], "COP")
    sensibleheatratio = convert_prop(props["Nominal Sensible Heat Ratio"], "")
    parent_name = parent.name.get
    name = e.name.get
    coiltype = niceClassName(e.iddObjectType.valueName)

    {"Terminal/Zone Equip Name" => parent_name, "Coil Type" => coiltype, "Name" => name, "Autosized" => autosized, "Nominal Capacity" => coolingcap, "Nominal Efficiency" => coolingeff, "Nominal SHR" => sensibleheatratio}
  end

  def properties_for_heating_coil(e, props, parent)
    autosized = "-"
    eff_units = "COP"
    heatingcap = ["-", "-"]
    heatingeff = ["-", "-"]
    case e.iddObjectType
      when OpenStudio::Model::CoilHeatingElectric.iddObjectType
        coil = e.to_CoilHeatingElectric.get
        autosized = coil.isNominalCapacityAutosized ? "Yes" : "No"
        heatingcap = convert_prop(props["Nominal Total Capacity"], "kW")
        heatingeff = convert_prop(props["Nominal Efficiency"], "%")
      when OpenStudio::Model::CoilHeatingGas.iddObjectType
        coil = e.to_CoilHeatingGas.get
        autosized = coil.isNominalCapacityAutosized ? "Yes" : "No"
        heatingcap = convert_prop(props["Nominal Total Capacity"], "kBtu/hr")
        heatingeff = convert_prop(props["Nominal Efficiency"], "COP")
      when OpenStudio::Model::CoilHeatingDXSingleSpeed.iddObjectType
        coil = e.to_CoilHeatingDXSingleSpeed.get
        autosized = (coil.isRatedTotalHeatingCapacityAutosized and coil.isRatedAirFlowRateAutosized) ? "Yes" : "No"
        heatingcap = convert_prop(props["Nominal Total Capacity"], "kBtu/hr")
        heatingeff = convert_prop(props["Nominal Efficiency"], "COP")
      when OpenStudio::Model::CoilHeatingWater.iddObjectType
        coil = e.to_CoilHeatingWater.get
        autosized = (coil.isMaximumWaterFlowRateAutosized and coil.isRatedCapacityAutosized and coil.isUFactorTimesAreaValueAutosized) ? "Yes" : "No"
        heatingcap = convert_prop(props["Nominal Total Capacity"], "kBtu/hr")
        heatingeff =["-", "-"]
      when OpenStudio::Model::CoilHeatingWaterBaseboard.iddObjectType
        coil = e.to_CoilHeatingWaterBaseboard.get
        autosized = (coil.isMaximumWaterFlowRateAutosized and coil.isUFactorTimesAreaValueAutosized) ? "Yes" : "No"
        heatingcap = convert_prop(props["Nominal Total Capacity"], "kBtu/hr")
        heatingeff =["-", "-"]
      when OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.iddObjectType
        coil = e.to_CoilHeatingWaterToAirHeatPumpEquationFit.get
        autosized = (coil.isRatedHeatingCapacityAutosized and coil.isRatedAirFlowRateAutosized and coil.isRatedWaterFlowRateAutosized) ? "Yes" : "No"
        heatingcap = convert_prop(props["Nominal Total Capacity"], "kBtu/hr")
        heatingeff = convert_prop(props["Nominal Efficiency"], "COP")
      else
        autosized = "?"
    end

    parent_name = parent.name.get
    name = e.name.get
    coiltype = niceClassName(e.iddObjectType.valueName)

    {"Terminal/Zone Equip Name" => parent_name, "Coil Type" => coiltype, "Name" => name, "Autosized" => autosized, "Nominal Capacity" => heatingcap, "Nominal Efficiency" => heatingeff}
  end

  def properties_for_fan(equipment, properties, parent)
    autosized = case equipment.iddObjectType
                  when OpenStudio::Model::FanConstantVolume.iddObjectType
                    fan = equipment.to_FanConstantVolume.get
                    fan.isMaximumFlowRateAutosized ? "Yes" : "No"
                  when OpenStudio::Model::FanVariableVolume.iddObjectType
                    fan = equipment.to_FanVariableVolume.get
                    fan.isMaximumFlowRateAutosized ? "Yes" : "No"
                  when OpenStudio::Model::FanOnOff.iddObjectType
                    fan = equipment.to_FanOnOff.get
                    fan.isMaximumFlowRateAutosized ? "Yes" : "No"
                  when OpenStudio::Model::FanZoneExhaust.iddObjectType
                    "N/A"
                  else
                    "?"
                end

    name = equipment.name.get
    parent_name = parent.name.get
    maxflowrate = convert_prop(properties["Max Air Flow Rate"], "cfm")
    fanpressure = convert_prop(properties["Delta Pressure"], "inH_{2}O")
    totalefficiency  = convert_prop(properties["Total Efficiency"], "%")
    ratedfanpower = convert_prop(properties["Rated Electric Power"], "W")
    {"Terminal/Zone Equip Name" => parent_name, "Fan Type" => niceClassName(equipment.iddObjectType.valueName), "Name" => name, "Autosized" => autosized, "Max Flow" => maxflowrate, "Efficiency" => totalefficiency, "Pressure" => fanpressure, "Power" => ratedfanpower}
  end

# Each equipment is grouped into Heating, Cooling or Fans and has properties extracted appropriate for that group.
# This method returns a tuple [equipment group, properties] where properties is a hash of name, value or name, [value, units] pairs
  def properties_for_zone_equipment(equipment, equipment_properties, parent)
# Make properties an empty hash if it was nil
    equipment_properties = equipment_properties || {}
    case
      when /^OS_Coil_Cooling/ =~ equipment.iddObjectType.valueName
        return "Cooling", properties_for_cooling_coil(equipment, equipment_properties, parent)
      when /^OS_Coil_Heating/ =~ equipment.iddObjectType.valueName
        return "Heating", properties_for_heating_coil(equipment, equipment_properties, parent)
      when /^OS_Fan/ =~ equipment.iddObjectType.valueName
        return "Fans", properties_for_fan(equipment, equipment_properties, parent)
      when OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.iddObjectType == equipment.iddObjectType
        baseboard = equipment.to_ZoneHVACBaseboardConvectiveElectric.get
        autosized = baseboard.isNominalCapacityAutosized ? "Yes" : "No"
        heatingcap = convert_prop(equipment_properties["Design Size Nominal Capacity"], "kW")
        name = baseboard.name.get
        coiltype = niceClassName(baseboard.iddObjectType.valueName)
        return "Heating", {"Terminal/Zone Equip Name" => name, "Coil Type" => coiltype, "Name" => name, "Autosized" => autosized, "Nominal Capacity" => heatingcap, "Nominal Efficiency" => [100, "%"]}
      else
        return nil, nil
    end
  end

  #define what happens when the measure is run
  def run(runner, user_arguments)
    super(runner, user_arguments)

    #use the built-in error checking
    if not runner.validateUserArguments(arguments(), user_arguments)
      return false
    end

    @runner = runner

    # get the last model and sql file

    model = runner.lastOpenStudioModel
    if model.empty?
      runner.registerError("Cannot find last model.")
      return false
    end
    model = model.get

    @sqlFile = runner.lastEnergyPlusSqlFile
    if @sqlFile.empty?
      runner.registerError("Cannot find last sql file.")
      return false
    end
    @sqlFile = @sqlFile.get
    model.setSqlFile(@sqlFile)

    @graph_data = []

# Collect and collate information about the hvac equipment
# When we are done we will have a hash of equipment keyed by equipment name
# who's values are hashes keyed by the property name.  The values of the
# property hashes are [value, unit] pairs
# Some types of equipment (for instance CoilCoolingCooledBeams) are not present
# in the database as of OS 1.5

# find table names, etc. in the SupportZoneHVACEquipFields
    tableNames = getDataByColumn( "TableName" )
    columnNames = getDataByColumn( "ColumnName" )
    rowNames = getDataByColumn( "RowName" )
    units = getDataByColumn( "Units" )
    values = getDataByColumn( "Value" )
    equipment_rows = tableNames.zip( columnNames, rowNames, units, values )
    equipment = {}
    equipment_rows.each do |r|
      _, field, name, units, value = r
      if name != "None"
        eh = equipment[name] || {}
        eh[field] = [value, units]
        equipment[name] = eh
      end
    end

    @zone_collection = []

    @testData = {}

# Go through each zone in the model and collect all the zone equipment
    model.getThermalZones.sort.each do |thermalZone|

      # Skip unconditioned zones
      if thermalZone.thermostatSetpointDualSetpoint.empty?
        @runner.registerInfo("Skipping #{thermalZone.name} because it is unconditioned.")
        next
      end

      # Skip plenums
      if thermalZone.isPlenum == true
        @runner.registerInfo("Skipping #{thermalZone.name} because it is a plenum.")
        next
      end

      zone_equipment = {}

      thermalZone.equipment.each do |e|
        childquipment = e.to_ParentObject.get.children
# Look for data on the top level equipment and each of that equipment's children
        found_primary_heat = false
        ([e] + childquipment).each do |ce|
          ename = ce.name.get.upcase
          reporting_type, equipment_properties = properties_for_zone_equipment(ce, equipment[ename], e)
          if equipment_properties
# The first heating coil in a zone equipment chain will be primary heating; all
# following heating coils will be marked as Backup Heating.
            if reporting_type == "Heating"
              reporting_type = "Backup Heating" if found_primary_heat
              found_primary_heat = true
            end
# Find the priority for heating or cooling equipment - the priority is based on the 'parent' zone equipment priority
            if reporting_type == "Heating"
              equipment_properties["Priority"] = (thermalZone.equipmentInHeatingOrder.index {|ze| ze.name.get == e.name.get && ze.iddObjectType == e.iddObjectType}) + 1
            end
            if reporting_type == "Cooling"
              equipment_properties["Priority"] = (thermalZone.equipmentInCoolingOrder.index {|ze| ze.name.get == e.name.get && ze.iddObjectType == e.iddObjectType}) + 1
            end
# If we don't yet have equipment of this type, make a new array.  Then add
# our equipment information to the array and update our zone equipment hash.
            equip_of_type = zone_equipment[reporting_type] || []
            equip_of_type << equipment_properties
            zone_equipment[reporting_type] = equip_of_type
          end
        end
      end

      zoneMetrics = {}
      zoneMetrics[:name] = !thermalZone.name.empty? ? thermalZone.name.get : ''
      zoneMetrics[:equipment] = zone_equipment
      zoneMetrics[:area] = (OpenStudio.convert( thermalZone.floorArea, "m^2", "ft^2" ).get).round(2)

      @currentZoneName = zoneMetrics[:name]

      vals = {}

      #vals[:va] = getDetailsData( "LightingSummary", "Entire Facility", "Interior Lighting", "#{zoneMetrics[:name]}%", "Lighting Power Density", "W/m2", "W/ft^2").round(2)
      #vals[:vb] = getDetailsData( "LightingSummary", "Entire Facility", "Interior Lighting", "#{zoneMetrics[:name]}%", "Full Load Hours/Week", "hr", "hr").round(2)

	  vals[:va] = getDetailsData( "LightingSummary", "Entire Facility", "Interior Lighting", "LIGHTS 3", "Lighting Power Density", "W/m2", "W/ft^2").round(2)
      vals[:vb] = getDetailsData( "LightingSummary", "Entire Facility", "Interior Lighting", "LIGHTS 3%", "Full Load Hours/Week", "hr", "hr").round(2)

      vals[:vc] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Electricity", "InteriorLights:Electricity:Zone:#{zoneMetrics[:name]}", "Electricity Annual Value", "GJ", "kWh").round(2)

      vals[:vd] = getDetailsData( "InputVerificationandResultsSummary", "Entire Facility", "Zone Summary", zoneMetrics[:name], "Plug and Process", "W/m2", "W/ft^2").round(2)

      vals[:ve] = getDetailsData( "InputVerificationandResultsSummary", "Entire Facility", "Zone Summary", zoneMetrics[:name], "Area", "m2", "ft^2").round(2)

      vals[:vf] = getDetailsData( "InputVerificationandResultsSummary", "Entire Facility", "Zone Summary", zoneMetrics[:name], "Conditioned (Y/N)", "", "s" )
      if ( vals[:vf] == "" ) then vals[:vf] = "No" end

      vals[:vg] = getDetailsData( "HVACSizingSummary", "Entire Facility", "Zone Sensible Heating", zoneMetrics[:name], "User Design Load", "W", "kBtu/hr" ).round(2)
      vals[:vh] = getDetailsData( "HVACSizingSummary", "Entire Facility", "Zone Sensible Heating", zoneMetrics[:name], "User Design Air Flow", "m3/s", "ft^3/s" ).round(2)
      vals[:vi] = getDetailsData( "HVACSizingSummary", "Entire Facility", "Zone Sensible Cooling", zoneMetrics[:name], "User Design Load", "W", "kBtu/hr" ).round(2)
      vals[:vj] = getDetailsData( "HVACSizingSummary", "Entire Facility", "Zone Sensible Cooling", zoneMetrics[:name], "User Design Air Flow", "m3/s", "ft^3/s" ).round(2)

      vals[:vk] = getDetailsData( "OutdoorAirSummary", "Entire Facility", "Average Outdoor Air During Occupied Hours", zoneMetrics[:name], "Mechanical Ventilation", "ach", "ach" ).round(2)
      vals[:vl] = getDetailsData( "OutdoorAirSummary", "Entire Facility", "Average Outdoor Air During Occupied Hours", zoneMetrics[:name], "Infiltration", "ach", "ach" ).round(2)

      vals[:vm] = getDetailsData( "InputVerificationandResultsSummary", "Entire Facility", "Zone Summary", zoneMetrics[:name], "People", "m2 per person", "ft^2/person" ).round(2)

      vals[:vn] = getDetailsData( "HVACSizingSummary", "Entire Facility", "Zone Sensible Cooling", zoneMetrics[:name], "Date/Time Of Peak {TIMESTAMP}", "", "s" )
      vals[:vo] = getDetailsData( "HVACSizingSummary", "Entire Facility", "Zone Sensible Heating", zoneMetrics[:name], "Date/Time Of Peak {TIMESTAMP}", "", "s" )

      vals[:vp] = getDetailsData( "SystemSummary", "Entire Facility", "Time Setpoint Not Met", zoneMetrics[:name], "During Heating", "hr", "hr" )
      vals[:vq] = getDetailsData( "SystemSummary", "Entire Facility", "Time Setpoint Not Met", zoneMetrics[:name], "During Cooling", "hr", "hr" )

      vals[:vr] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Gas", "InteriorEquipment:Gas:Zone:#{zoneMetrics[:name]}", "Electricity Annual Value", "GJ", "Therm" ).round(2)
      vals[:vs] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Electricity", "InteriorEquipment:Electricity:Zone:#{zoneMetrics[:name]}", "Electricity Annual Value", "GJ", "kWh" ).round(2)

      vals[:vt] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Gas", "InteriorEquipment:Gas:Zone:#{zoneMetrics[:name]}", "Gas Maximum  Value", "W", "kBtu/hr" ).round(2)
      vals[:vu] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Gas", "InteriorEquipment:Gas:Zone:#{zoneMetrics[:name]}", "Timestamp of Maximum {TIMESTAMP}", "", "s" )

      vals[:vv] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Electricity", "InteriorLights:Electricity:Zone:#{zoneMetrics[:name]}", "Electricity Maximum Value", "W", "kW" ).round(2)
      vals[:vw] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Electricity", "InteriorLights:Electricity:Zone:#{zoneMetrics[:name]}", "Timestamp of Maximum {TIMESTAMP}", "", "s" )

      #X unused

      vals[:vy] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Electricity", "InteriorEquipment:Electricity:Zone:#{zoneMetrics[:name]}", "Electricity Maximum Value", "W", "kW" ).round(2)
      vals[:vz] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Electricity", "InteriorEquipment:Electricity:Zone:#{zoneMetrics[:name]}", "Timestamp of Maximum  {TIMESTAMP}", "", "s" )

      vals[:vaa] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "InteriorEquipment:DistrictHeating:Zone:#{zoneMetrics[:name]}", "Annual Value", "GJ", "kBtu" ).round(2)
      vals[:vab] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "InteriorEquipment:DistrictHeating:Zone:#{zoneMetrics[:name]}", "Maximum Value", "W", "kBtu/hr" ).round(2)
      vals[:vac] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "InteriorEquipment:DistrictHeating:Zone:#{zoneMetrics[:name]}", "Timestamp of Maximum {TIMESTAMP}", "", "s" )

      vals[:vad] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "Heating:EnergyTransfer:Zone:#{zoneMetrics[:name]}", "Annual Value", "GJ", "kBtu" ).round(2)
      vals[:vae] = (getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "Heating:EnergyTransfer:Zone:#{zoneMetrics[:name]}", "Maximum Value", "W", "kBtu/hr")/zoneMetrics[:area]).round(2)
      vals[:vaf] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "Heating:EnergyTransfer:Zone:#{zoneMetrics[:name]}", "Timestamp of Maximum {TIMESTAMP}", "", "s" )

      vals[:vag] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "Cooling:EnergyTransfer:Zone:#{zoneMetrics[:name]}", "Annual Value", "GJ", "kBtu" ).round(2)
      vals[:vah] = (getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "Cooling:EnergyTransfer:Zone:#{zoneMetrics[:name]}", "Maximum Value", "W", "kBtu/hr")/zoneMetrics[:area]).round(2)
      vals[:vai] = getDetailsData( "EnergyMeters", "Entire Facility", "Annual and Peak Values - Other", "Cooling:EnergyTransfer:Zone:#{zoneMetrics[:name]}", "Timestamp of Maximum {TIMESTAMP}", "", "s" )

      vals[:vaj] = zoneHeatComponentCalc("People",zoneMetrics )
      vals[:vak] = zoneHeatComponentCalc("Lights",zoneMetrics )
      vals[:val] = zoneHeatComponentCalc("Equipment",zoneMetrics )
      vals[:vam] = zoneHeatComponentCalc("Refrigeration",zoneMetrics )
      vals[:van] = zoneHeatComponentCalc("Water Use Equipment",zoneMetrics )
      vals[:vao] = zoneHeatComponentCalc("HVAC Equipment Losses",zoneMetrics )
      vals[:vap] = zoneHeatComponentCalc("Power Generation Equipment",zoneMetrics )
      vals[:vaq] = zoneHeatComponentCalc("Infiltration",zoneMetrics )
      vals[:var] = zoneHeatComponentCalc("Zone Ventilation",zoneMetrics )
      vals[:vas] = zoneHeatComponentCalc("Interzone Mixing",zoneMetrics )
      vals[:vat] = zoneHeatComponentCalc("Exterior Wall",zoneMetrics )
      vals[:vau] = zoneHeatComponentCalc("Interzone Wall",zoneMetrics )
      vals[:vav] = zoneHeatComponentCalc("Ground Contact Wall",zoneMetrics )
      vals[:vaw] = zoneHeatComponentCalc("Other Wall",zoneMetrics )
      vals[:vax] = zoneHeatComponentCalc("Opaque Door",zoneMetrics )
      vals[:vay] = zoneHeatComponentCalc("Roof",zoneMetrics )
      vals[:vaz] = zoneHeatComponentCalc("Interzone Ceiling",zoneMetrics )
      vals[:vba] = zoneHeatComponentCalc("Other Roof",zoneMetrics )
      vals[:vbb] = zoneHeatComponentCalc("Exterior Floor",zoneMetrics )
      vals[:vbc] = zoneHeatComponentCalc("Interzone Floor",zoneMetrics )
      vals[:vbd] = zoneHeatComponentCalc("Ground Contact Floor",zoneMetrics )
      vals[:vbe] = zoneHeatComponentCalc("Other Floor",zoneMetrics )
      vals[:vbf] = zoneHeatComponentCalc("Fenestration Conduction",zoneMetrics )
      vals[:vbg] = zoneHeatComponentCalc("Fenestration Solar",zoneMetrics )

      vals[:vbh] = getDetailsData( "Zone Component Load Summary", "#{zoneMetrics[:name]}", "Heating Peak Conditions", "Time of Peak Load", "Value", "", "s" )

      vals[:vbi] = zoneCoolComponentCalc("People",zoneMetrics )
      vals[:vbj] = zoneCoolComponentCalc("Lights",zoneMetrics )
      vals[:vbk] = zoneCoolComponentCalc("Equipment",zoneMetrics )
      vals[:vbl] = zoneCoolComponentCalc("Refrigeration",zoneMetrics )
      vals[:vbm] = zoneCoolComponentCalc("Water Use Equipment",zoneMetrics )
      vals[:vbn] = zoneCoolComponentCalc("HVAC Equipment Losses",zoneMetrics )
      vals[:vbo] = zoneCoolComponentCalc("Power Generation Equipment",zoneMetrics )
      vals[:vbp] = zoneCoolComponentCalc("Infiltration",zoneMetrics )
      vals[:vbq] = zoneCoolComponentCalc("Zone Ventilation",zoneMetrics )
      vals[:vbr] = zoneCoolComponentCalc("Interzone Mixing",zoneMetrics )
      vals[:vbs] = zoneCoolComponentCalc("Exterior Wall",zoneMetrics )
      vals[:vbt] = zoneCoolComponentCalc("Interzone Wall",zoneMetrics )
      vals[:vbu] = zoneCoolComponentCalc("Ground Contact Wall",zoneMetrics )
      vals[:vbv] = zoneCoolComponentCalc("Other Wall",zoneMetrics )
      vals[:vbw] = zoneCoolComponentCalc("Opaque Door",zoneMetrics )
      vals[:vbx] = zoneCoolComponentCalc("Roof",zoneMetrics )
      vals[:vby] = zoneCoolComponentCalc("Interzone Ceiling",zoneMetrics )
      vals[:vbz] = zoneCoolComponentCalc("Other Roof",zoneMetrics )
      vals[:vca] = zoneCoolComponentCalc("Exterior Floor",zoneMetrics )
      vals[:vcb] = zoneCoolComponentCalc("Interzone Floor",zoneMetrics )
      vals[:vcc] = zoneCoolComponentCalc("Ground Contact Floor",zoneMetrics )
      vals[:vcd] = zoneCoolComponentCalc("Other Floor",zoneMetrics )
      vals[:vce] = zoneCoolComponentCalc("Fenestration Conduction",zoneMetrics )
      vals[:vcf] = zoneCoolComponentCalc("Fenestration Solar",zoneMetrics )

      vals[:vcg] = getDetailsData( "Zone Component Load Summary", "#{zoneMetrics[:name]}", "Cooling Peak Conditions", "Time of Peak Load", "Value", "", "s" )

    #vals = loadTestVals( vals )

      vals[:sumBasicHeating] = (vals[:vaj] + vals[:vak] + vals[:val] + vals[:vam] + vals[:vaq] + vals[:var] + vals[:vas]).round(2)
      vals[:sumBasicCooling] = (vals[:vbi] + vals[:vbj] + vals[:vbk] + vals[:vbl] + vals[:vbp] + vals[:vbq] + vals[:vbr]).round(2)

      vals[:sumOtherHeating] = (vals[:van] + vals[:vao] + vals[:vap]).round(2)
      vals[:sumOtherCooling] = (vals[:vbm] + vals[:vbn] + vals[:vbo]).round(2)

      vals[:sumWallDoorHeating] = (vals[:vat] + vals[:vau] + vals[:vav] + vals[:vaw] + vals[:vax]).round(2)
      vals[:sumWallDoorCooling] = (vals[:vbs] + vals[:vbt] + vals[:vbu] + vals[:vbv] + vals[:vbw]).round(2)

      vals[:sumRoofCeilingHeating] = (vals[:vay] + vals[:vaz] + vals[:vba]).round(2)
      vals[:sumRoofCeilingCooling] = (vals[:vbx] + vals[:vby] + vals[:vbz]).round(2)

      vals[:sumFloorHeating] = (vals[:vbb] + vals[:vbc] + vals[:vbd] + vals[:vbe]).round(2)
      vals[:sumFloorCooling] = (vals[:vca] + vals[:vcb] + vals[:vcc] + vals[:vcd]).round(2)

      vals[:sumWindowsHeating] = (vals[:vbf] + vals[:vbg]).round(2)
      vals[:sumWindowsCooling] = (vals[:vce] + vals[:vcf]).round(2)

      vals[:sumHeatingTotal] = (vals[:sumBasicHeating] + vals[:sumOtherHeating] + vals[:sumWallDoorHeating] + vals[:sumRoofCeilingHeating] + vals[:sumFloorHeating] + vals[:sumWindowsHeating]).round(2)
      vals[:sumCoolingTotal] = (vals[:sumBasicCooling] + vals[:sumOtherCooling] + vals[:sumWallDoorCooling] + vals[:sumRoofCeilingCooling] + vals[:sumFloorCooling] + vals[:sumWindowsCooling]).round(2)

      zoneMetrics[:vals] = vals

      @zone_collection.push( zoneMetrics )

      stacked_bars( zoneMetrics )

    end

	@zone_collection = @zone_collection.sort_by { |z| z[:name] }

    equipment_lengths = @zone_collection.map { |z| z[:equipment].values.map { |equip_list| equip_list.length } }
    max_zone_equipments = equipment_lengths.flatten.max

    # Convert the graph data to JSON
    # This measure requires ruby 2.0.0 to create the JSON for the report graph
    if RUBY_VERSION >= "2.0.0"
      require 'json'
      @graph_data = @graph_data.to_json
    else
      runner.registerInfo("This Measure needs Ruby 2.0.0 to generate timeseries graphs on the report.  You have Ruby #{RUBY_VERSION}.  OpenStudio 1.4.2 and higher user Ruby 2.0.0.")
    end

    web_asset_path = OpenStudio::getSharedResourcesPath() / OpenStudio::Path.new("web_assets")

    html_in = getResourceFileData( "report.html.in" )

    # configure template with variable values
    renderer = ERB.new(html_in)
    html_out = renderer.result(binding)

    writeResourceFileData( "report.html", html_out )
    #copyResourceFile( "graph_resource.js" )
    #copyResourceFile( "style_resource.css" )

    #closing the sql file
    @sqlFile.close()

    #reporting final condition
    runner.registerFinalCondition("Successfully finished writing 'Zone Report'.")

    return true

  end #end the run method

  def zoneHeatComponentCalc( component, zoneMetrics )
    (getDetailsData( "Zone Component Load Summary", "#{zoneMetrics[:name]}", "Estimated Heating Peak Load Components", component, "Total", "W", "Btu/hr") / zoneMetrics[:area]).round(2)
  end

  def zoneCoolComponentCalc( component, zoneMetrics )
    (getDetailsData( "Zone Component Load Summary", "#{zoneMetrics[:name]}", "Estimated Cooling Peak Load Components", component, "Total", "W", "Btu/hr") / zoneMetrics[:area]).round(2)
  end

    def stacked_bars( zoneMetrics )

    #people, lights, equipment, refrigeration, other, infiltration, zone ventilation,
    #interzone mixing, walls/doors, roof/ceiling, floor, windows

    vals = zoneMetrics[:vals]

    heatingVals = [vals[:vaj],
                      vals[:vak],
                      vals[:val],
                      vals[:vam],
                      vals[:sumOtherHeating],
                      vals[:vaq],
                      vals[:var],
                      vals[:vas],
                      vals[:sumWallDoorHeating],
                      vals[:sumRoofCeilingHeating],
                      vals[:sumFloorHeating],
                      vals[:sumWindowsHeating]];

    coolingVals = [vals[:vbi],
                      vals[:vbj],
                      vals[:vbk],
                      vals[:vbl],
                      vals[:sumOtherCooling],
                      vals[:vbp],
                      vals[:vbq],
                      vals[:vbr],
                      vals[:sumWallDoorCooling],
                      vals[:sumRoofCeilingCooling],
                      vals[:sumFloorCooling],
                      vals[:sumWindowsCooling]];

    positiveHeating = heatingVals.select{ |v| v >= 0 }.inject{|sum,x| sum + x } || 0
    negativeHeating = heatingVals.select{ |v| v < 0 }.inject{|sum,x| sum + x } || 0

    positiveCooling = coolingVals.select{ |v| v >= 0 }.inject{|sum,x| sum + x } || 0
    negativeCooling = coolingVals.select{ |v| v < 0 }.inject{|sum,x| sum + x } || 0

    maxPositive = positiveHeating > positiveCooling ? positiveHeating : positiveCooling
    maxNegative = negativeHeating < negativeCooling ? negativeHeating : negativeCooling

    maxPositive = maxPositive == 0 ? maxNegative * -0.20 : maxPositive
    maxNegative = maxNegative == 0 ? maxPositive * -0.10 : maxNegative

    maxPositive = maxPositive + ( maxPositive * 0.20 ).round(2)
    maxNegative = maxNegative + ( maxNegative * 0.10 ).round(2)

    stacked_vals = [[ 0, maxPositive, maxNegative, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
                    [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, vals[:sumHeatingTotal], 0 ],
                    [ 2,
                      vals[:vaj],
                      vals[:vak],
                      vals[:val],
                      vals[:vam],
                      vals[:sumOtherHeating],
                      vals[:vaq],
                      vals[:var],
                      vals[:vas],
                      vals[:sumWallDoorHeating],
                      vals[:sumRoofCeilingHeating],
                      vals[:sumFloorHeating],
                      vals[:sumWindowsHeating],
                      0,
                      0],
                    [ 3,
                      vals[:vbi],
                      vals[:vbj],
                      vals[:vbk],
                      vals[:vbl],
                      vals[:sumOtherCooling],
                      vals[:vbp],
                      vals[:vbq],
                      vals[:vbr],
                      vals[:sumWallDoorCooling],
                      vals[:sumRoofCeilingCooling],
                      vals[:sumFloorCooling],
                      vals[:sumWindowsCooling],
                      0,
                      0],
                    [ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, vals[:sumCoolingTotal] ],
                    [ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]]

    # Add the hourly load data to JSON for the report.html
    graph = {}
    graph["title"] = ""
    graph["xaxislabel"] = ""
    graph["yaxislabel"] = "Contribution Btu/hr/ft2"
    graph["labels"] = %w(index, people lights equipment refrigeration other infiltration zone_ventilation interzone_mixing walls/doors roof/ceiling floor windows net/heating net/cooling)
    graph["colors"] = ["#888855", "#AAAA55", "#3333AA", "#8888FF", "#888888", "#9999FF", "#AAAAFF", "#AA6666", "#777733", "#888833", "#999933", "#9999FF", "#FF9999", "#9999FF" ]
    graph["data"] = stacked_vals

    @graph_data << graph
  end

  def getPctLoad( val, total )
    if val != "" && total != 0 then
      return (val * 100 / total).round(2)
    else
      return 0
    end
  end

  def getResourceFileData( fileName )
    data_in_path = "#{File.dirname(__FILE__)}/resources/#{fileName}"
    if !File.exist?(data_in_path)
        data_in_path = "#{File.dirname(__FILE__)}/#{fileName}"
    end

    html_in = ""
    File.open(data_in_path, 'r') do |file|
      html_in = file.read
    end

    html_in
  end

  def writeResourceFileData( fileName, data )
    File.open("./#{fileName}", 'w') do |file|
      file << data
      # make sure data is written to the disk one way or the other
      begin
        file.fsync
      rescue
        file.flush
      end
    end
  end

  # Fetch a value from the tabulardatawithstrings database view
  # If final_units is "s" the value is returned unchanged as a string
  # Otherwise the value is converted from units to final_units - units is specified in energy plus style (m2, m3, etc)
  # and final_units should be open studio style (m^2, m^3, ...)
  # If the data is not found or cannot be converted a warning is registered and "" or 0.0 is returned.
  def getDetailsData( report, forstring, table, row, column, units, final_units)

    if report == "Zone Component Load Summary" then
      forstring.upcase!
    end

	if report == "HVACSizingSummary" then
      row.upcase!
    end

    str_HVACEquipment_query = "SELECT Value FROM tabulardatawithstrings WHERE "
    str_HVACEquipment_query << "ReportName='#{report}' AND "
    str_HVACEquipment_query << "ReportForString='#{forstring}' AND "
    str_HVACEquipment_query << "TableName='#{table}' AND "
    str_HVACEquipment_query << "RowName LIKE '#{row}' AND "
    str_HVACEquipment_query << "ColumnName='#{column}' AND "
    str_HVACEquipment_query << "Units='#{units}'"

    query_results = @sqlFile.execAndReturnFirstString(str_HVACEquipment_query)

    if query_results.empty?

      @runner.registerWarning("Could not get data for #{report} #{forstring} #{table} #{row} #{column}.")
      return "s" == final_units ? "" : 0.0

    else
      r = query_results.get
      if report == "Zone Component Load Summary" then
        @testData["#{@currentZoneName}_#{table}_#{row}"] = r
      end

      if "s" == final_units
        return r
      else
        converted = OpenStudio::convert(r.to_f, eplus_to_openstudio(units), final_units)
        if converted.empty?
          @runner.registerError("Could not convert #{r} from #{units} to #{final_units}")
          return 0.0
        else
          return converted.get.round(2)
        end
      end

    end

  end

  def getDataByColumn( colName )

      strvec_HVACEquipment_query = "SELECT #{colName} FROM tabulardatawithstrings WHERE "
      strvec_HVACEquipment_query << "ReportName='EquipmentSummary' and "
      strvec_HVACEquipment_query << "ReportForString='Entire Facility'"
      strvec_HVACEquipment_query << "ORDER BY TableName, ColumnName, RowName, Units, Value"

      query_results = @sqlFile.execAndReturnVectorOfString(strvec_HVACEquipment_query).get

      if query_results.empty?
        @runner.registerError("Could not get data for requested Column #{colName}.")
        return []
      else
        return query_results
      end
  end

  # Accessor to support unit tests
  def zone_collection
	@zone_collection
  end

end #end the measure

#this allows the measure to be use by the application
ZoneReportCopy.new.registerWithApplication


text:
package org.artifactory.model.xstream.fs;

import org.artifactory.fs.MetadataEntryInfo;

/**
 * @author freds
 * @date Nov 11, 2008
 */
public class MetadataEntry implements MetadataEntryInfo {
    private final String metadataName;
    private final String xmlContent;

    public MetadataEntry(String metadataName, String xmlContent) {
        if (metadataName == null) {
            throw new IllegalArgumentException("Metadata name cannot be null!");
        }
        this.metadataName = metadataName;
        this.xmlContent = xmlContent;
    }

    @Override
    public String getMetadataName() {
        return metadataName;
    }

    @Override
    public String getXmlContent() {
        return xmlContent;
    }
}


text:
//
//  Constant.h
//  ALLocalLife
//
//  Created by 王可成 on 15/11/21.
//  Copyright © 2015年 AL. All rights reserved.
//

#ifndef Constant_h
#define Constant_h

#ifdef DEBUG

#define DSLog(...) NSLog(__VA_ARGS__)

#else

#define DSLog(...)

#endif

#define kFirstLogin @"kFirstTimeLogin"

#define kScale kScreenHeight / 480 * 0.5

#define kScreenBounds [UIScreen mainScreen].bounds
#define kScreenWidth kScreenBounds.size.width
#define kScreenHeight kScreenBounds.size.height
#define kStatusBarHeight 20
#define kNavBarHeight 44
#define kTabBarHeight 49
//分组数
#define kHomeGroups 3
#define kIsLogined @"isLogined"

//ALLoginVc
#define kPassword @"password"
#define kUserName @"username"
#define kUserLogo @"userLogo"
#define kKeepPassword @"kKeepPassword"
//#define kWeiBoRedirectURI @"https://api.weibo.com/oauth2/default.html"
#define kWeiBoRedirectURI @"http://sns.whalecloud.com/sina2/callback"
#define kSinaWeiBoAppKey @"1396052786"

//ALHTTPSession
#define kBaseURL @"http://www.qd-life.com/"

#endif /* Constant_h */


text:
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/interest_group/interest_group_update_manager.h"

#include <stddef.h>

#include "base/bind.h"
#include "base/callback.h"
#include "base/containers/span.h"
#include "base/json/json_string_value_serializer.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/browser/interest_group/interest_group_storage.h"
#include "content/browser/interest_group/interest_group_update.h"
#include "content/browser/interest_group/storage_interest_group.h"
#include "net/base/isolation_info.h"
#include "net/base/net_errors.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/client_security_state.mojom.h"
#include "third_party/blink/public/common/interest_group/interest_group.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {

namespace {

// 10 kb update size limit. We are potentially fetching many interest group
// updates, so don't let this get too large.
constexpr size_t kMaxUpdateSize = 10 * 1024;

// The maximum amount of time that the update process can run before it gets
// cancelled for taking too long.
constexpr base::TimeDelta kMaxUpdateRoundDuration = base::Minutes(10);

// The maximum number of groups that can be updated at the same time.
constexpr int kMaxParallelUpdates = 5;

constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("interest_group_update_fetcher", R"(
        semantics {
          sender: "Interest group periodic update fetcher"
          description:
            "Fetches periodic updates of FLEDGE interest groups previously "
            "joined by navigator.joinAdInterestGroup(). FLEDGE allow sites to "
            "store persistent interest groups that are only accessible to "
            "special on-device ad auction worklets run via "
            "navigator.runAdAuction(). JavaScript running in the context of a "
            "frame cannot read interest groups, but it can request that all "
            "interest groups owned by the current frame's origin be updated by "
            "fetching JSON from the registered update URL for each interest "
            "group."
            "See https://github.com/WICG/turtledove/blob/main/FLEDGE.md and "
            "https://developer.chrome.com/docs/privacy-sandbox/fledge/"
          trigger:
            "Fetched upon a navigator.updateAdInterestGroups() call. Also "
            "triggered upon navigator.runAdAuction() completion for interest "
            "groups that participated in the auction."
          data: "URL registered for updating this interest group."
          destination: WEBSITE
        }
        policy {
          cookies_allowed: NO
          setting:
            "These requests are controlled by a feature flag that is off by "
            "default now. When enabled, they can be disabled by the Privacy"
            " Sandbox setting."
          policy_exception_justification:
            "These requests are triggered by a website."
        })");

// TODO(crbug.com/1186444): Report errors to devtools for the TryToCopy*().
// functions.

// Name and owner are optional in `dict` (parsed server JSON response), but
// must match `name` and `owner`, respectively, if either is specified. Returns
// true if the check passes, and false otherwise.
[[nodiscard]] bool ValidateNameAndOwnerIfPresent(
    const blink::InterestGroupKey& group_key,
    const base::Value::Dict& dict) {
  const std::string* maybe_owner = dict.FindString("owner");
  if (maybe_owner && url::Origin::Create(GURL(*maybe_owner)) != group_key.owner)
    return false;
  const std::string* maybe_name = dict.FindString("name");
  if (maybe_name && *maybe_name != group_key.name)
    return false;
  return true;
}

// Copies the `priorityVector` JSON field into `priority_vector`. Returns
// true if the JSON is valid and the copy completed.
[[nodiscard]] bool TryToCopyPriorityVector(
    const base::Value::Dict& dict,
    absl::optional<base::flat_map<std::string, double>>& priority_vector) {
  const base::Value* maybe_dict = dict.Find("priorityVector");
  if (!maybe_dict)
    return true;
  if (!maybe_dict->is_dict())
    return false;

  // Extract all key/value pairs to a vector before writing to a flat_map, since
  // flat_map insertion is O(n).
  std::vector<std::pair<std::string, double>> pairs;
  for (const auto pair : maybe_dict->GetDict()) {
    if (pair.second.is_int() || pair.second.is_double()) {
      pairs.emplace_back(pair.first, pair.second.GetDouble());
      continue;
    }
    return false;
  }
  priority_vector = base::flat_map<std::string, double>(std::move(pairs));
  return true;
}

// Copies the prioritySignalsOverrides JSON field into
// `priority_signals_overrides`, returns true if the JSON is valid and the copy
// completed. Maps nulls to nullopt, which means a value should be deleted from
// the stored interset group.
[[nodiscard]] bool TryToCopyPrioritySignalsOverrides(
    const base::Value::Dict& dict,
    absl::optional<base::flat_map<std::string, absl::optional<double>>>&
        priority_signals_overrides) {
  const base::Value* maybe_dict = dict.Find("prioritySignalsOverrides");
  if (!maybe_dict)
    return true;
  if (!maybe_dict->is_dict())
    return false;

  std::vector<std::pair<std::string, absl::optional<double>>> pairs;
  for (const auto pair : maybe_dict->GetDict()) {
    if (pair.second.is_none()) {
      pairs.emplace_back(pair.first, absl::nullopt);
      continue;
    }
    if (pair.second.is_int() || pair.second.is_double()) {
      pairs.emplace_back(pair.first, pair.second.GetDouble());
      continue;
    }
    return false;
  }
  priority_signals_overrides =
      base::flat_map<std::string, absl::optional<double>>(std::move(pairs));
  return true;
}

// Copies the executionMode JSON field into `interest_group_update`, returns
// true iff the JSON is valid and the copy completed.
[[nodiscard]] bool TryToCopyExecutionMode(
    const base::Value::Dict& dict,
    InterestGroupUpdate& interest_group_update) {
  const std::string* maybe_execution_mode = dict.FindString("executionMode");
  if (!maybe_execution_mode)
    return true;
  if (*maybe_execution_mode == "compatibility") {
    interest_group_update.execution_mode =
        blink::InterestGroup::ExecutionMode::kCompatibilityMode;
  } else if (*maybe_execution_mode == "groupByOrigin") {
    interest_group_update.execution_mode =
        blink::InterestGroup::ExecutionMode::kGroupedByOriginMode;
  } else {
    return false;
  }
  return true;
}

// Copies the trustedBiddingSignals list JSON field into
// `interest_group_update`, returns true iff the JSON is valid and the copy
// completed.
[[nodiscard]] bool TryToCopyTrustedBiddingSignalsKeys(
    const base::Value::Dict& dict,
    InterestGroupUpdate& interest_group_update) {
  const base::Value::List* maybe_update_trusted_bidding_signals_keys =
      dict.FindList("trustedBiddingSignalsKeys");
  if (!maybe_update_trusted_bidding_signals_keys)
    return true;
  std::vector<std::string> trusted_bidding_signals_keys;
  for (const base::Value& keys_value :
       *maybe_update_trusted_bidding_signals_keys) {
    const std::string* maybe_key = keys_value.GetIfString();
    if (!maybe_key)
      return false;
    trusted_bidding_signals_keys.push_back(*maybe_key);
  }
  interest_group_update.trusted_bidding_signals_keys =
      trusted_bidding_signals_keys;
  return true;
}

// Helper for TryToCopyAds() and TryToCopyAdComponents().
[[nodiscard]] absl::optional<std::vector<blink::InterestGroup::Ad>> ExtractAds(
    const base::Value::List& ads_list) {
  std::vector<blink::InterestGroup::Ad> ads;
  for (const base::Value& ads_value : ads_list) {
    const base::Value::Dict* ads_dict = ads_value.GetIfDict();
    if (!ads_dict)
      return absl::nullopt;
    const std::string* maybe_render_url = ads_dict->FindString("renderUrl");
    if (!maybe_render_url)
      return absl::nullopt;
    blink::InterestGroup::Ad ad;
    ad.render_url = GURL(*maybe_render_url);
    const base::Value* maybe_metadata = ads_dict->Find("metadata");
    if (maybe_metadata) {
      std::string metadata;
      JSONStringValueSerializer serializer(&metadata);
      if (!serializer.Serialize(*maybe_metadata)) {
        // Binary blobs shouldn't be present, but it's possible we exceeded the
        // max JSON depth.
        return absl::nullopt;
      }
      ad.metadata = std::move(metadata);
    }
    ads.push_back(std::move(ad));
  }
  return ads;
}

// Copies the `ads` list JSON field into `interest_group_update`, returns true
// iff the JSON is valid and the copy completed.
[[nodiscard]] bool TryToCopyAds(const base::Value::Dict& dict,
                                InterestGroupUpdate& interest_group_update) {
  const base::Value::List* maybe_ads = dict.FindList("ads");
  if (!maybe_ads)
    return true;
  absl::optional<std::vector<blink::InterestGroup::Ad>> maybe_extracted_ads =
      ExtractAds(*maybe_ads);
  if (!maybe_extracted_ads)
    return false;
  interest_group_update.ads = std::move(*maybe_extracted_ads);
  return true;
}

// Copies the `adComponents` list JSON field into `interest_group_update`,
// returns true iff the JSON is valid and the copy completed.
[[nodiscard]] bool TryToCopyAdComponents(
    const base::Value::Dict& dict,
    InterestGroupUpdate& interest_group_update) {
  const base::Value::List* maybe_ads = dict.FindList("adComponents");
  if (!maybe_ads)
    return true;
  absl::optional<std::vector<blink::InterestGroup::Ad>> maybe_extracted_ads =
      ExtractAds(*maybe_ads);
  if (!maybe_extracted_ads)
    return false;
  interest_group_update.ad_components = std::move(*maybe_extracted_ads);
  return true;
}

absl::optional<InterestGroupUpdate> ParseUpdateJson(
    const blink::InterestGroupKey& group_key,
    const data_decoder::DataDecoder::ValueOrError& result) {
  // TODO(crbug.com/1186444): Report to devtools.
  if (!result.has_value()) {
    return absl::nullopt;
  }
  const base::Value::Dict* dict = result->GetIfDict();
  if (!dict) {
    return absl::nullopt;
  }
  if (!ValidateNameAndOwnerIfPresent(group_key, *dict)) {
    return absl::nullopt;
  }
  InterestGroupUpdate interest_group_update;
  const base::Value* maybe_priority_value = dict->Find("priority");
  if (maybe_priority_value) {
    // If the field is specified, it must be an integer or a double.
    if (!maybe_priority_value->is_int() && !maybe_priority_value->is_double())
      return absl::nullopt;
    interest_group_update.priority = maybe_priority_value->GetDouble();
  }
  const base::Value* maybe_enable_bidding_signals_prioritization =
      dict->Find("enableBiddingSignalsPrioritization");
  if (maybe_enable_bidding_signals_prioritization) {
    // If the field is specified, it must be a bool.
    if (!maybe_enable_bidding_signals_prioritization->is_bool())
      return absl::nullopt;
    interest_group_update.enable_bidding_signals_prioritization =
        maybe_enable_bidding_signals_prioritization->GetBool();
  }
  if (!TryToCopyPriorityVector(*dict, interest_group_update.priority_vector) ||
      !TryToCopyPrioritySignalsOverrides(
          *dict, interest_group_update.priority_signals_overrides) ||
      !TryToCopyExecutionMode(*dict, interest_group_update)) {
    return absl::nullopt;
  }
  const std::string* maybe_bidding_url = dict->FindString("biddingLogicUrl");
  if (maybe_bidding_url)
    interest_group_update.bidding_url = GURL(*maybe_bidding_url);
  const std::string* maybe_bidding_wasm_helper_url =
      dict->FindString("biddingWasmHelperUrl");
  if (maybe_bidding_wasm_helper_url) {
    interest_group_update.bidding_wasm_helper_url =
        GURL(*maybe_bidding_wasm_helper_url);
  }
  const std::string* maybe_update_trusted_bidding_signals_url =
      dict->FindString("trustedBiddingSignalsUrl");
  if (maybe_update_trusted_bidding_signals_url) {
    interest_group_update.trusted_bidding_signals_url =
        GURL(*maybe_update_trusted_bidding_signals_url);
  }
  if (!TryToCopyTrustedBiddingSignalsKeys(*dict, interest_group_update)) {
    return absl::nullopt;
  }
  if (!TryToCopyAds(*dict, interest_group_update)) {
    return absl::nullopt;
  }
  if (!TryToCopyAdComponents(*dict, interest_group_update)) {
    return absl::nullopt;
  }
  return interest_group_update;
}

}  // namespace

InterestGroupUpdateManager::InterestGroupUpdateManager(
    InterestGroupManagerImpl* manager,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
    : manager_(manager),
      max_update_round_duration_(kMaxUpdateRoundDuration),
      max_parallel_updates_(kMaxParallelUpdates),
      url_loader_factory_(std::move(url_loader_factory)) {}

InterestGroupUpdateManager::~InterestGroupUpdateManager() = default;

void InterestGroupUpdateManager::UpdateInterestGroupsOfOwner(
    const url::Origin& owner,
    network::mojom::ClientSecurityStatePtr client_security_state) {
  owners_to_update_.Enqueue(owner, std::move(client_security_state));
  MaybeContinueUpdatingCurrentOwner();
}

void InterestGroupUpdateManager::UpdateInterestGroupsOfOwners(
    base::span<url::Origin> owners,
    network::mojom::ClientSecurityStatePtr client_security_state) {
  // Shuffle the list of interest group owners for fairness.
  base::RandomShuffle(owners.begin(), owners.end());
  for (const url::Origin& owner : owners) {
    UpdateInterestGroupsOfOwner(owner, client_security_state.Clone());
  }
}

void InterestGroupUpdateManager::set_max_update_round_duration_for_testing(
    base::TimeDelta delta) {
  max_update_round_duration_ = delta;
}

void InterestGroupUpdateManager::set_max_parallel_updates_for_testing(
    int max_parallel_updates) {
  max_parallel_updates_ = max_parallel_updates;
}

InterestGroupUpdateManager::OwnersToUpdate::OwnersToUpdate() = default;

InterestGroupUpdateManager::OwnersToUpdate::~OwnersToUpdate() = default;

bool InterestGroupUpdateManager::OwnersToUpdate::Empty() const {
  return owners_to_update_.empty();
}

const url::Origin& InterestGroupUpdateManager::OwnersToUpdate::FrontOwner()
    const {
  return owners_to_update_.front();
}

network::mojom::ClientSecurityStatePtr
InterestGroupUpdateManager::OwnersToUpdate::FrontSecurityState() const {
  return security_state_map_.at(FrontOwner()).Clone();
}

bool InterestGroupUpdateManager::OwnersToUpdate::Enqueue(
    const url::Origin& owner,
    network::mojom::ClientSecurityStatePtr client_security_state) {
  if (!security_state_map_.emplace(owner, std::move(client_security_state))
           .second) {
    return false;
  }
  owners_to_update_.emplace_back(owner);
  return true;
}

void InterestGroupUpdateManager::OwnersToUpdate::PopFront() {
  security_state_map_.erase(owners_to_update_.front());
  owners_to_update_.pop_front();
}

void InterestGroupUpdateManager::OwnersToUpdate::Clear() {
  owners_to_update_.clear();
  security_state_map_.clear();
}

void InterestGroupUpdateManager::MaybeContinueUpdatingCurrentOwner() {
  if (num_in_flight_updates_ > 0 || waiting_on_db_read_)
    return;

  if (owners_to_update_.Empty()) {
    // This update round is finished, there's no more work to do.
    last_update_started_ = base::TimeTicks::Min();
    return;
  }

  if (last_update_started_ == base::TimeTicks::Min()) {
    // It appears we're staring a new update round; mark the time we started the
    // round.
    last_update_started_ = base::TimeTicks::Now();
  } else if (base::TimeTicks::Now() - last_update_started_ >
             max_update_round_duration_) {
    // We've been updating for too long; cancel all outstanding updates.
    owners_to_update_.Clear();
    last_update_started_ = base::TimeTicks::Min();
    return;
  }

  GetInterestGroupsForUpdate(
      owners_to_update_.FrontOwner(),
      base::BindOnce(
          &InterestGroupUpdateManager::DidUpdateInterestGroupsOfOwnerDbLoad,
          weak_factory_.GetWeakPtr(), owners_to_update_.FrontOwner()));
}

void InterestGroupUpdateManager::GetInterestGroupsForUpdate(
    const url::Origin& owner,
    base::OnceCallback<void(std::vector<StorageInterestGroup>)> callback) {
  DCHECK_EQ(num_in_flight_updates_, 0);
  DCHECK(!waiting_on_db_read_);
  waiting_on_db_read_ = true;
  manager_->GetInterestGroupsForUpdate(
      owner, /*groups_limit=*/max_parallel_updates_, std::move(callback));
}

void InterestGroupUpdateManager::DidUpdateInterestGroupsOfOwnerDbLoad(
    url::Origin owner,
    std::vector<StorageInterestGroup> storage_groups) {
  DCHECK_EQ(owner, owners_to_update_.FrontOwner());
  DCHECK_EQ(num_in_flight_updates_, 0);
  DCHECK(waiting_on_db_read_);
  DCHECK_LE(storage_groups.size(),
            static_cast<unsigned int>(max_parallel_updates_));
  waiting_on_db_read_ = false;
  if (storage_groups.empty()) {
    // All interest groups for `owner` are up to date, so we can pop it off the
    // queue.
    owners_to_update_.PopFront();
    MaybeContinueUpdatingCurrentOwner();
    return;
  }
  net::IsolationInfo per_update_isolation_info =
      net::IsolationInfo::CreateTransient();

  for (auto& storage_group : storage_groups) {
    manager_->QueueKAnonymityUpdateForInterestGroup(storage_group);
    if (!storage_group.interest_group.daily_update_url)
      continue;
    // TODO(behamilton): Don't update unless daily update url is k-anonymous
    ++num_in_flight_updates_;
    base::UmaHistogramCounts100000(
        "Ads.InterestGroup.Net.RequestUrlSizeBytes.Update",
        storage_group.interest_group.daily_update_url->spec().size());
    auto resource_request = std::make_unique<network::ResourceRequest>();
    resource_request->url =
        std::move(storage_group.interest_group.daily_update_url).value();
    resource_request->redirect_mode = network::mojom::RedirectMode::kError;
    resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
    resource_request->request_initiator = owner;
    resource_request->trusted_params =
        network::ResourceRequest::TrustedParams();
    resource_request->trusted_params->isolation_info =
        per_update_isolation_info;
    resource_request->trusted_params->client_security_state =
        owners_to_update_.FrontSecurityState();
    auto simple_url_loader = network::SimpleURLLoader::Create(
        std::move(resource_request), kTrafficAnnotation);
    simple_url_loader->SetTimeoutDuration(base::Seconds(30));
    auto simple_url_loader_it =
        url_loaders_.insert(url_loaders_.end(), std::move(simple_url_loader));
    (*simple_url_loader_it)
        ->DownloadToString(
            url_loader_factory_.get(),
            base::BindOnce(&InterestGroupUpdateManager::
                               DidUpdateInterestGroupsOfOwnerNetFetch,
                           weak_factory_.GetWeakPtr(), simple_url_loader_it,
                           blink::InterestGroupKey(
                               std::move(storage_group.interest_group.owner),
                               std::move(storage_group.interest_group.name))),
            kMaxUpdateSize);
  }
}

void InterestGroupUpdateManager::DidUpdateInterestGroupsOfOwnerNetFetch(
    UrlLoadersList::iterator simple_url_loader_it,
    blink::InterestGroupKey group_key,
    std::unique_ptr<std::string> fetch_body) {
  DCHECK_EQ(group_key.owner, owners_to_update_.FrontOwner());
  DCHECK_GT(num_in_flight_updates_, 0);
  DCHECK(!waiting_on_db_read_);
  std::unique_ptr<network::SimpleURLLoader> simple_url_loader =
      std::move(*simple_url_loader_it);
  url_loaders_.erase(simple_url_loader_it);
  // TODO(crbug.com/1186444): Report HTTP error info to devtools.
  if (!fetch_body) {
    ReportUpdateFailed(group_key,
                       /*delay_type=*/simple_url_loader->NetError() ==
                               net::ERR_INTERNET_DISCONNECTED
                           ? UpdateDelayType::kNoInternet
                           : UpdateDelayType::kNetFailure);
    return;
  }
  base::UmaHistogramCounts100000(
      "Ads.InterestGroup.Net.ResponseSizeBytes.Update", fetch_body->size());
  data_decoder::DataDecoder::ParseJsonIsolated(
      *fetch_body,
      base::BindOnce(
          &InterestGroupUpdateManager::DidUpdateInterestGroupsOfOwnerJsonParse,
          weak_factory_.GetWeakPtr(), std::move(group_key)));
}

void InterestGroupUpdateManager::DidUpdateInterestGroupsOfOwnerJsonParse(
    blink::InterestGroupKey group_key,
    data_decoder::DataDecoder::ValueOrError result) {
  DCHECK_EQ(group_key.owner, owners_to_update_.FrontOwner());
  DCHECK_GT(num_in_flight_updates_, 0);
  DCHECK(!waiting_on_db_read_);
  absl::optional<InterestGroupUpdate> interest_group_update =
      ParseUpdateJson(group_key, result);
  if (!interest_group_update) {
    ReportUpdateFailed(group_key, UpdateDelayType::kParseFailure);
    return;
  }
  UpdateInterestGroup(group_key, std::move(*interest_group_update));
}

void InterestGroupUpdateManager::UpdateInterestGroup(
    const blink::InterestGroupKey& group_key,
    InterestGroupUpdate update) {
  manager_->UpdateInterestGroup(
      group_key, std::move(update),
      base::BindOnce(
          &InterestGroupUpdateManager::OnUpdateInterestGroupCompleted,
          weak_factory_.GetWeakPtr(), group_key));
}

void InterestGroupUpdateManager::OnUpdateInterestGroupCompleted(
    const blink::InterestGroupKey& group_key,
    bool success) {
  if (!success) {
    ReportUpdateFailed(group_key, UpdateDelayType::kParseFailure);
    return;
  }
  OnOneUpdateCompleted();
}

void InterestGroupUpdateManager::OnOneUpdateCompleted() {
  DCHECK_GT(num_in_flight_updates_, 0);
  --num_in_flight_updates_;
  MaybeContinueUpdatingCurrentOwner();
}

void InterestGroupUpdateManager::ReportUpdateFailed(
    const blink::InterestGroupKey& group_key,
    UpdateDelayType delay_type) {
  if (delay_type != UpdateDelayType::kNoInternet) {
    manager_->ReportUpdateFailed(
        group_key,
        /*parse_failure=*/delay_type == UpdateDelayType::kParseFailure);
  }

  if (delay_type == UpdateDelayType::kNoInternet) {
    // If the internet is disconnected, no more updating is possible at the
    // moment. As we are now stopping update work, and it is an invariant
    // that `owners_to_update_` only stores owners that will eventually
    // be processed, we clear `owners_to_update_` to ensure that future
    // update attempts aren't blocked.
    //
    // To avoid violating the invariant that we're always updating the front of
    // the queue, only clear we encounter this error on the last in-flight
    // update.
    if (num_in_flight_updates_ == 1)
      owners_to_update_.Clear();
  }

  OnOneUpdateCompleted();
}

}  // namespace content


text:
from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns('',
    url(r'^user$', 'faqflow.views.user', name='user'),
    url(r'^questions$', 'faqflow.views.questions', name='questions'),
    url(r'^questions/(?P<qid>\d+)$', 'faqflow.views.questions', name='questions'),
    url(r'^questions/(?P<qid>\d+)/answers$', 'faqflow.views.answers', name='answers'),
    url(r'^questions/(?P<qid>\d+)/answers/(?P<aid>\d+)$', 'faqflow.views.answers', name='answers'),
    url(r'^test$', TemplateView.as_view(template_name='faqflow/faqflow.html')),
)


text:
from workshops.models import Tag
from workshops.tests.base import TestBase

class TestTagManager(TestBase):
    def setUp(self):
        super()._setUpTags()

    def test_main_tags(self):
        # Arrange
        expected = [
            Tag.objects.get(name="DC"),
            Tag.objects.get(name="ITT"),
            Tag.objects.get(name="LC"),
            Tag.objects.get(name="SWC"),
            Tag.objects.get(name="TTT"),
            Tag.objects.get(name="WiSE"),
        ]
        # Act
        tags = Tag.objects.main_tags().order_by("name")
        # Assert
        self.assertEqual(list(tags), expected)

    def test_carpentries_tags(self):
        # Arrange
        expected = [
            Tag.objects.get(name="DC"),
            Tag.objects.get(name="LC"),
            Tag.objects.get(name="SWC"),
        ]
        # Act
        tags = Tag.objects.carpentries().order_by("name")
        # Assert
        self.assertEqual(list(tags), expected)

    def test_strings(self):
        # Arrange
        expected = ["DC", "LC", "SWC"]
        # Act
        tags = Tag.objects.carpentries().order_by("name").strings()
        # Assert
        self.assertEqual(list(tags), expected)


text:
@implementation UIImage (Image)

// 创建保持原始状态,不被 Tint Color 渲染的图片
+ (instancetype)imageOriginalWithName:(NSString *)imageName
{
    UIImage *image = [UIImage imageNamed:imageName];

    return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}

// 切图 > 正元图
- (instancetype)MBB_circleImage
{
    // 启动图形上下文
    // 比例因素:当前点与像素比例
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
    // 描述裁剪区域
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    // 设置裁剪区域
    [path addClip];
    // 画图片
    [self drawAtPoint:CGPointZero];
    // 取出图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    // 关闭图形上下文
    UIGraphicsEndImageContext();

    return image;
}

// 创建圆形图片
+ (instancetype)MBB_circleImageNamed:(NSString *)imageName
{
    return [[self imageNamed:imageName] MBB_circleImage];
}
@end