Merge remote-tracking branch 'origin/master'
	
		
		2 files added
	
		
		5 files modified
	
	
 
	
	
	
	
	
	
	
	
|  |  |  | 
|---|
|  |  |  | package com.moral.monitor.dao; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import org.springframework.stereotype.Repository; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.moral.monitor.entity.Equipment; | 
|---|
|  |  |  | import com.moral.monitor.entity.History; | 
|---|
|  |  |  | import com.moral.monitor.entity.Logger; | 
|---|
|  |  |  | import org.springframework.stereotype.Repository; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Repository | 
|---|
|  |  |  | public interface JobDao { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public List<Map<String, String>> findAdjustByMac(String mac); | 
|---|
|  |  |  | public Map<String,Object> findEquWithAdjustsByMac(String mac); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void updateStateByMac(String mac, int state); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | import org.slf4j.LoggerFactory; | 
|---|
|  |  |  | import org.springframework.amqp.core.Message; | 
|---|
|  |  |  | import org.springframework.amqp.core.MessageListener; | 
|---|
|  |  |  | import org.springframework.amqp.core.MessageProperties; | 
|---|
|  |  |  | import org.springframework.amqp.rabbit.core.RabbitTemplate; | 
|---|
|  |  |  | import org.springframework.beans.factory.annotation.Value; | 
|---|
|  |  |  | import org.springframework.core.io.ClassPathResource; | 
|---|
|  |  |  | 
|---|
|  |  |  | import com.moral.monitor.dao.TaskDao; | 
|---|
|  |  |  | import com.moral.monitor.entity.History; | 
|---|
|  |  |  | import com.moral.monitor.entity.Sensor; | 
|---|
|  |  |  | import com.moral.monitor.service.RedisService; | 
|---|
|  |  |  | import com.moral.monitor.util.RedisUtil; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public class TaskListener implements MessageListener { | 
|---|
|  |  |  | 
|---|
|  |  |  | protected MongoTemplate mongoTemplate; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private Logger logger = LoggerFactory.getLogger(TaskListener.class); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | RedisService redisService; | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | public void onMessage(Message msg) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | if(StringUtils.isEmpty(ver) || StringUtils.isEmpty(mac)) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Map<String, Float> adjustMap; | 
|---|
|  |  |  | String adjust_key = "adjust_" + mac; | 
|---|
|  |  |  | if(RedisUtil.hasKey(redisTemplate, adjust_key)) { | 
|---|
|  |  |  | adjustMap = JSON.parseObject(RedisUtil.get(redisTemplate, adjust_key), new TypeReference<Map<String, Float>>() {}); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | adjustMap = getAdjustData(mac); | 
|---|
|  |  |  | RedisUtil.set(redisTemplate, adjust_key, JSON.toJSONString(adjustMap)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if(!adjustMap.isEmpty()) { | 
|---|
|  |  |  | //获取缓存中的校准值map | 
|---|
|  |  |  | Map<String, Float> adjustMap = redisService.getAdjustsByMac(mac); | 
|---|
|  |  |  | if(adjustMap!=null&&!adjustMap.isEmpty()) { | 
|---|
|  |  |  | for (Map.Entry<String, Float> entry : adjustMap.entrySet()) { | 
|---|
|  |  |  | String key = entry.getKey(); | 
|---|
|  |  |  | if(msgData.containsKey(key)) { | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //        System.out.println(message); | 
|---|
|  |  |  | //        System.out.println(JSON.toJSONString(msgData)); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | //mongoTemplate.insert(JSON.toJSONString(histories), "data"); | 
|---|
|  |  |  | mongoTemplate.insert(new_message, "data"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private Map<String, Float> getAdjustData(String mac) { | 
|---|
|  |  |  | List<Map<String, String>> adjusts = jobDao.findAdjustByMac(mac); | 
|---|
|  |  |  | Map<String, Float> dataMap = new HashMap<String, Float>(); | 
|---|
|  |  |  | for (int i = 0; i < adjusts.size(); i++) { | 
|---|
|  |  |  | Map adjust = adjusts.get(i); | 
|---|
|  |  |  | if(adjust.get("value") != null) { | 
|---|
|  |  |  | String key = String.valueOf(adjust.get("key")); | 
|---|
|  |  |  | String data = String.valueOf(adjust.get("value")); | 
|---|
|  |  |  | BigDecimal value = new BigDecimal(data); | 
|---|
|  |  |  | value.setScale(3, BigDecimal.ROUND_HALF_UP); | 
|---|
|  |  |  | dataMap.put(key, value.floatValue()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return dataMap; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //三级警报值阀值 | 
|---|
|  |  |  | private static Map<String,Double[]> alarmLevles =new HashMap<String, Double[]>(); | 
|---|
|  |  |  | /* | 
|---|
|  |  |  | 
|---|
|  |  |  | //根据三级警报阀值,确定设备状态 | 
|---|
|  |  |  | private int detEquState(Map<String,String> data) { | 
|---|
|  |  |  | int state = 0; | 
|---|
|  |  |  | Map<String, Object> equMap = new HashMap<String, Object>(); | 
|---|
|  |  |  | if(data!=null) { | 
|---|
|  |  |  | for(String key:alarmLevles.keySet()) { | 
|---|
|  |  |  | String value = data.get(key); | 
|---|
|  |  |  | 
|---|
|  |  |  | if(val>=arr[index]) { | 
|---|
|  |  |  | //如果当前状态级别更高就取当前状态。否则保持之前状态 | 
|---|
|  |  |  | state = (index>state)?index:state; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | String e_key = "level"+Integer.toString(index); | 
|---|
|  |  |  | Object e_States = equMap.get(e_key); | 
|---|
|  |  |  | if(e_States!=null&&e_States instanceof List) { | 
|---|
|  |  |  | ((List)e_States).add(key); | 
|---|
|  |  |  | }else { | 
|---|
|  |  |  | e_States = new ArrayList<String>(); | 
|---|
|  |  |  | equMap.put(e_key, e_States); | 
|---|
|  |  |  | ((List)e_States).add(key); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //当前状态到达最大级别不再遍历,跳出循环 | 
|---|
|  |  |  | if(state == (arr.length-1)) { | 
|---|
|  |  |  | equMap.put(e_key, e_States); | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | equMap.put("state", state);//设备状态 | 
|---|
|  |  |  | redisService.setEquState(data.get("mac"),equMap); | 
|---|
|  |  |  | return state; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | private String getDate() { | 
|---|
|  |  |  | Date d = new Date(); | 
|---|
|  |  |  | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | 
|---|
|  |  |  | return formatter.format(d); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | package com.moral.monitor.service; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * @author fengxiang | 
|---|
|  |  |  | * @Time:2017年11月7日 下午2:42:19 | 
|---|
|  |  |  | * @version 1.0 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public interface RedisService { | 
|---|
|  |  |  | public void setEquState(String mac,Map<String,Object> equWithStateMap); | 
|---|
|  |  |  | public Map<String,Object> getEquState(String mac); | 
|---|
|  |  |  | /* | 
|---|
|  |  |  | * 根据 mac地址 获取校正值map | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public Map<String,Float> getAdjustsByMac(String mac); | 
|---|
|  |  |  | } | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | package com.moral.monitor.service.impl; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.util.ArrayList; | 
|---|
|  |  |  | import java.util.HashMap; | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  | import java.util.concurrent.TimeUnit; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.annotation.Resource; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import org.apache.commons.lang3.StringUtils; | 
|---|
|  |  |  | import org.springframework.data.redis.core.RedisTemplate; | 
|---|
|  |  |  | import org.springframework.stereotype.Service; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.alibaba.fastjson.JSON; | 
|---|
|  |  |  | import com.alibaba.fastjson.TypeReference; | 
|---|
|  |  |  | import com.moral.monitor.dao.JobDao; | 
|---|
|  |  |  | import com.moral.monitor.service.RedisService; | 
|---|
|  |  |  | import com.moral.monitor.util.RedisUtil; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * @author fengxiang | 
|---|
|  |  |  | * @Time:2017年11月7日 上午10:16:33 | 
|---|
|  |  |  | * @version 1.0 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @Service | 
|---|
|  |  |  | public class RedisServiceImpl implements RedisService{ | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | JobDao jobDao; | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | RedisTemplate<String, String> redis; | 
|---|
|  |  |  | private static final String ADJUSTS = "adjusts"; | 
|---|
|  |  |  | private static final String ORG_ID = "orgId"; | 
|---|
|  |  |  | private static final String AREA_CODE = "areaCode"; | 
|---|
|  |  |  | private static final String MONITORPOINT_ID= "monitorpoint"; | 
|---|
|  |  |  | //设备静态数据,不常改动。 | 
|---|
|  |  |  | private static String getStaticEquKey(String mac) { | 
|---|
|  |  |  | return "static_equ_"+mac; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public void setStaticEqu(String mac,Map<String,Object> equMap) { | 
|---|
|  |  |  | RedisUtil.set(redis, getStaticEquKey(mac),JSON.toJSONString(equMap)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public Map<String,Object> getStaticEqu(String mac) { | 
|---|
|  |  |  | String staticEqu_key = getStaticEquKey(mac); | 
|---|
|  |  |  | String staticEquJson = RedisUtil.get(redis,staticEqu_key); | 
|---|
|  |  |  | Map<String,Object> equMap = null; | 
|---|
|  |  |  | if(StringUtils.isEmpty(staticEquJson)) { | 
|---|
|  |  |  | equMap = jobDao.findEquWithAdjustsByMac(mac); | 
|---|
|  |  |  | if(equMap!=null) { | 
|---|
|  |  |  | //没有赋值的adjust,不储存 | 
|---|
|  |  |  | List<Map<String,Object>> adjustList = (List<Map<String, Object>>) equMap.get(ADJUSTS); | 
|---|
|  |  |  | List<Object> adjustListWithData = new ArrayList<Object>(); | 
|---|
|  |  |  | //list to map | 
|---|
|  |  |  | for(Map<String,Object> adjust:adjustList) { | 
|---|
|  |  |  | if(adjust.get("value")!=null) { | 
|---|
|  |  |  | //没有值的清空 | 
|---|
|  |  |  | adjustListWithData.add(adjust); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | equMap.put(ADJUSTS,adjustListWithData); | 
|---|
|  |  |  | setStaticEqu(mac,equMap); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }else { | 
|---|
|  |  |  | equMap = JSON.parseObject(staticEquJson,new TypeReference<Map<String,Object>>(){}); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return equMap; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /* | 
|---|
|  |  |  | * 根据 mac地址 获取校正值map | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public Map<String,Float> getAdjustsByMac(String mac){ | 
|---|
|  |  |  | Map<String,Object> equMap = getStaticEqu(mac); | 
|---|
|  |  |  | Map<String,Float> adjustMap = null; | 
|---|
|  |  |  | if(equMap!=null) { | 
|---|
|  |  |  | List<Map<String,Object>> adjustList = (List<Map<String, Object>>) equMap.get(ADJUSTS); | 
|---|
|  |  |  | if(adjustList!=null) { | 
|---|
|  |  |  | adjustMap = new HashMap<String, Float>(); | 
|---|
|  |  |  | //list to map | 
|---|
|  |  |  | for(Map<String,Object> adjust:adjustList) { | 
|---|
|  |  |  | if(adjust.get("value")!=null) { | 
|---|
|  |  |  | adjustMap.put(adjust.get("key").toString(), Float.valueOf(adjust.get("value").toString())); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return adjustMap; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //格式:state_组织ID_地区ID_监控点ID_mac | 
|---|
|  |  |  | private String getEquStateKey(String mac) { | 
|---|
|  |  |  | Map<String,Object> equMap = getStaticEqu(mac); | 
|---|
|  |  |  | if(equMap!=null) { | 
|---|
|  |  |  | String orgId = equMap.get(ORG_ID)==null?"$":equMap.get(ORG_ID).toString(); | 
|---|
|  |  |  | String areaCode = equMap.get(AREA_CODE)==null?"$":equMap.get(AREA_CODE).toString(); | 
|---|
|  |  |  | String mpointId = equMap.get(MONITORPOINT_ID)==null?"$":equMap.get(MONITORPOINT_ID).toString(); | 
|---|
|  |  |  | return "state_"+orgId+"_"+areaCode+"_"+mpointId+"_"+mac; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | else { | 
|---|
|  |  |  | return "state_$_$_$_"+mac; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //把含有状态的设备监控功能数据 存储到redis | 
|---|
|  |  |  | public void setEquState(String mac,Map<String,Object> equWithStateMap) { | 
|---|
|  |  |  | String key = getEquStateKey(mac); | 
|---|
|  |  |  | String equWithStateJsonStr = JSON.toJSONString(equWithStateMap); | 
|---|
|  |  |  | RedisUtil.set(redis,key,equWithStateJsonStr,10,TimeUnit.SECONDS); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //从redis获取含有状态的设备监控功能数据 | 
|---|
|  |  |  | public Map<String,Object> getEquState(String mac) { | 
|---|
|  |  |  | String equ_key = getEquStateKey(mac); | 
|---|
|  |  |  | String equWithStateJsonStr = RedisUtil.get(redis, equ_key); | 
|---|
|  |  |  | Map<String,Object> equMap= JSON.parseObject(equWithStateJsonStr,new TypeReference<Map<String,Object>>() {}); | 
|---|
|  |  |  | return equMap; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | package com.moral.monitor.util; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.util.Set; | 
|---|
|  |  |  | import java.util.concurrent.TimeUnit; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import org.springframework.data.redis.core.RedisTemplate; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public class RedisUtil { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public static boolean hasKey(RedisTemplate<String, String> redis, String key) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return redis.hasKey(key); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public static void set(RedisTemplate<String, String> redis, String key, String value) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | redis.opsForValue().set(key, value); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public static String get(RedisTemplate<String, String> redis, String key) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return redis.opsForValue().get(key); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public static void set(RedisTemplate<String, String> redis, String key, String value, | 
|---|
|  |  |  | int timeout,TimeUnit unit) { | 
|---|
|  |  |  | redis.opsForValue().set(key, value,timeout, unit); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public static Set<String> keys(RedisTemplate<String, String> redis,String pattern) { | 
|---|
|  |  |  | return redis.keys(pattern); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | <mapper namespace="com.moral.monitor.dao.JobDao"> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <resultMap type="HashMap" id="adjustResultMap"> | 
|---|
|  |  |  | <result column="owner_id"   property="orgId" javaType="java.lang.String" /> | 
|---|
|  |  |  | <result column="areacode"   property="areaCode" javaType="java.lang.String" /> | 
|---|
|  |  |  | <result column="monitorpoint"   property="monitorpointId" javaType="java.lang.String" /> | 
|---|
|  |  |  | <collection property="adjusts" column="id" javaType="java.util.List"  ofType="java.util.Map"> | 
|---|
|  |  |  | <result column="mac_key"   property="key" javaType="java.lang.String" /> | 
|---|
|  |  |  | <result column="value"   property="value" javaType="java.lang.Float" /> | 
|---|
|  |  |  | </collection> | 
|---|
|  |  |  | </resultMap> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <select id="findAdjustByMac" resultMap="adjustResultMap"> | 
|---|
|  |  |  | select c.mac_key, d.`value` | 
|---|
|  |  |  | <select id="findEquWithAdjustsByMac" resultMap="adjustResultMap"> | 
|---|
|  |  |  | select a.id,a.owner_id,a.monitorpoint,e.areacode,c.mac_key,d.`value` | 
|---|
|  |  |  | from equipment a | 
|---|
|  |  |  | inner join mac b on a.id = b.equipment_id | 
|---|
|  |  |  | inner join sensor c on b.sensor = c.id | 
|---|
|  |  |  | left join sensoradjust d on b.id = d.sen_dev_id | 
|---|
|  |  |  | left join monitorpoint e on e.id = a.monitorpoint | 
|---|
|  |  |  | where a.mac = #{0} | 
|---|
|  |  |  | </select> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | "enable":1 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e3":{ | 
|---|
|  |  |  | "level1":5000, | 
|---|
|  |  |  | "level2":8000, | 
|---|
|  |  |  | "level3":20000 | 
|---|
|  |  |  | "level1":20000, | 
|---|
|  |  |  | "level2":30000, | 
|---|
|  |  |  | "level3":40000 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e4":{ | 
|---|
|  |  |  | "level1":30, | 
|---|
|  |  |  | 
|---|
|  |  |  | "enable":1 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e11":{ | 
|---|
|  |  |  | "level1":0.05, | 
|---|
|  |  |  | "level2":0.475, | 
|---|
|  |  |  | "level3":1.6, | 
|---|
|  |  |  | "level1":50, | 
|---|
|  |  |  | "level2":475, | 
|---|
|  |  |  | "level3":1600, | 
|---|
|  |  |  | "enable":1 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e12":{ | 
|---|
|  |  |  | 
|---|
|  |  |  | "level3":120 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e14":{ | 
|---|
|  |  |  | "level1":2, | 
|---|
|  |  |  | "level2":4, | 
|---|
|  |  |  | "level3":6 | 
|---|
|  |  |  | "level1":100, | 
|---|
|  |  |  | "level2":200, | 
|---|
|  |  |  | "level3":300 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e15":{ | 
|---|
|  |  |  | "level1":0.16, | 
|---|
|  |  |  | "level2":0.3, | 
|---|
|  |  |  | "level3":0.8, | 
|---|
|  |  |  | "level1":160, | 
|---|
|  |  |  | "level2":300, | 
|---|
|  |  |  | "level3":800, | 
|---|
|  |  |  | "enable":1 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e16":{ | 
|---|
|  |  |  | "level1":0.04, | 
|---|
|  |  |  | "level2":0.18, | 
|---|
|  |  |  | "level3":0.565, | 
|---|
|  |  |  | "level1":40, | 
|---|
|  |  |  | "level2":180, | 
|---|
|  |  |  | "level3":565, | 
|---|
|  |  |  | "enable":1 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e17":{ | 
|---|
|  |  |  | 
|---|
|  |  |  | "level3":8 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | "e19":{ | 
|---|
|  |  |  | "level1":800, | 
|---|
|  |  |  | "level2":1200, | 
|---|
|  |  |  | "level3":1600 | 
|---|
|  |  |  | "level1":3000, | 
|---|
|  |  |  | "level2":4000, | 
|---|
|  |  |  | "level3":5000 | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|