Commit a3f95d16 authored by 梁光意's avatar 梁光意

修改获取实时和历史变量数据

parent 73350370
...@@ -53,9 +53,9 @@ public class BaseRestController { ...@@ -53,9 +53,9 @@ public class BaseRestController {
protected String businessFiledData; protected String businessFiledData;
@Value("${dc_client.interfaces.variableHistoryDataList}") @Value("${dc_client.interfaces.variableCodeHistoryList}")
protected String variableHistoryDataList; protected String variableHistoryDataList;
@Value("${dc_client.interfaces.variableRealTimeDataList}") @Value("${dc_client.interfaces.variableAllDataList}")
protected String variableRealTimeDataList; protected String variableRealTimeDataList;
@Value("${dc_client.interfaces.filedValue}") @Value("${dc_client.interfaces.filedValue}")
protected String filedValue; protected String filedValue;
...@@ -67,8 +67,8 @@ public class BaseRestController { ...@@ -67,8 +67,8 @@ public class BaseRestController {
@Value("${dc_client.interfaces.variableHistoryStatus}") @Value("${dc_client.interfaces.variableHistoryStatus}")
protected String variableHistoryStatus; protected String variableHistoryStatus;
@Value("${dc_client.interfaces.historyCurve}") // @Value("${dc_client.interfaces.historyCurve}")
protected String historyCurve; // protected String historyCurve;
......
...@@ -86,11 +86,11 @@ public class VariableController extends BaseRestController{ ...@@ -86,11 +86,11 @@ public class VariableController extends BaseRestController{
}); });
} }
@PostMapping("/real-time") @PostMapping("/all/data")
@ApiOperation("获取变量实时数据") @ApiOperation("获取变量全部数据(按时间段)")
@ApiImplicitParam(name = "appId", value = "租户id", required = true,dataTypeClass = String.class) @ApiImplicitParam(name = "appId", value = "租户id", required = true,dataTypeClass = String.class)
public R<Map<String,List<Map<String,Object>>>> getVariableRealTimeDataList(HttpServletRequest request,@PathVariable String appId, public R<Map<String,List<Object>>> getVariableRealTimeDataList(HttpServletRequest request,@PathVariable String appId,
@RequestBody VariableRealTimeDTO variableDTO) { @RequestBody VariableAllDataDTO variableDTO) {
return call(() -> { return call(() -> {
CurrentUser currentUser = getCurrentUser(request); CurrentUser currentUser = getCurrentUser(request);
return variableService.getVariableRealTimeDataList(dcClientHost + variableRealTimeDataList, return variableService.getVariableRealTimeDataList(dcClientHost + variableRealTimeDataList,
...@@ -116,10 +116,10 @@ public class VariableController extends BaseRestController{ ...@@ -116,10 +116,10 @@ public class VariableController extends BaseRestController{
}); });
} }
@PostMapping("/history") @PostMapping("/variableCode/history")
@ApiOperation("获取变量历史数据") @ApiOperation("以变量为X轴获取变量历史数据")
@ApiImplicitParam(name = "appId", value = "租户id", required = true,dataTypeClass = String.class) @ApiImplicitParam(name = "appId", value = "租户id", required = true,dataTypeClass = String.class)
public R<List<Map<String,List<Map<String,Object>>>>> getVariableHistoryDataList(HttpServletRequest request,@PathVariable String appId, public R<Map<String,Object>> getVariableHistoryDataList(HttpServletRequest request,@PathVariable String appId,
@RequestBody VariableHistoryDataDTO variableDTO) { @RequestBody VariableHistoryDataDTO variableDTO) {
return call(() -> { return call(() -> {
CurrentUser currentUser = getCurrentUser(request); CurrentUser currentUser = getCurrentUser(request);
...@@ -130,16 +130,16 @@ public class VariableController extends BaseRestController{ ...@@ -130,16 +130,16 @@ public class VariableController extends BaseRestController{
} }
@GetMapping("/history-curve") // @PostMapping("/history-curve")
@ApiOperation("获取变量历史曲线数据") // @ApiOperation("获取变量历史曲线数据")
@ApiImplicitParam(name = "appId", value = "租户id", required = true,dataTypeClass = String.class) // @ApiImplicitParam(name = "appId", value = "租户id", required = true,dataTypeClass = String.class)
public R<List<Map<String, Object>>> getVariableHistoryCurve(HttpServletRequest request,@PathVariable String appId, // public R<Map<String,List<Map<String,Object>>>> getVariableHistoryCurve(HttpServletRequest request,@PathVariable String appId,
VariableHistoryCurveDataDTO variableDTO) { // @RequestBody VariableHistoryCurveDataDTO variableDTO) {
return call(() -> { // return call(() -> {
CurrentUser currentUser = getCurrentUser(request); // CurrentUser currentUser = getCurrentUser(request);
return variableService.getVariableHistoryCurve(variableDTO,currentUser,dcClientHost+historyCurve); // return variableService.getVariableHistoryCurve(variableDTO,currentUser,dcClientHost+historyCurve);
}); // });
} // }
@PostMapping("/send") @PostMapping("/send")
@ApiOperation("下发") @ApiOperation("下发")
......
...@@ -15,22 +15,14 @@ import java.util.Map; ...@@ -15,22 +15,14 @@ import java.util.Map;
**/ **/
@ApiModel("变量DTO") @ApiModel("变量DTO")
@Data @Data
public class VariableRealTimeDTO { public class VariableAllDataDTO {
// @ApiModelProperty(value = "所属设备", required = true)
// private String deviceId;
// @ApiModelProperty(value = "变量id", required = true)
// private String variableId;
// @ApiModelProperty(value = "变量Code", required = true)
// private String variableCode;
@ApiModelProperty(value = "开始时间(时间戳)",required = true) @ApiModelProperty(value = "开始时间(时间戳)",required = true)
private String startTime; private String startTime;
@ApiModelProperty(value = "结束时间(时间戳)", required = true) @ApiModelProperty(value = "结束时间(时间戳)", required = true)
private String endTime; private String endTime;
@ApiModelProperty(value = "(如果x轴为变量直接填yyyy-MM-dd HH:mm:ss)请填时间格式如(yyyy-MM-dd HH:mm:ss)", required = true)
private String format;
@ApiModelProperty(value = "变量信息", required = true) @ApiModelProperty(value = "变量信息", required = true)
private List<VariableSearchDTO> variableSearchList; private List<VariableSearchDTO> variableSearchList;
@ApiModelProperty(value = "统计维度,如果是时间填time,如果是变量填variableCode", required = true)
private String x;
} }
...@@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel; ...@@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.util.List;
/** /**
* slm-bi * slm-bi
* 历史曲线DTO * 历史曲线DTO
...@@ -13,16 +15,11 @@ import lombok.Data; ...@@ -13,16 +15,11 @@ import lombok.Data;
@ApiModel("变量DTO") @ApiModel("变量DTO")
@Data @Data
public class VariableHistoryCurveDataDTO { public class VariableHistoryCurveDataDTO {
@ApiModelProperty(value = "所属设备", required = true)
private String deviceId;
@ApiModelProperty(value = "变量id", required = true)
private String variableId;
@ApiModelProperty(value = "变量Code", required = true)
private String variableCode;
@ApiModelProperty(value = "开始时间(时间戳)",required = true) @ApiModelProperty(value = "开始时间(时间戳)",required = true)
private String startTime; private String startTime;
@ApiModelProperty(value = "结束时间(时间戳)", required = true) @ApiModelProperty(value = "结束时间(时间戳)", required = true)
private String endTime; private String endTime;
@ApiModelProperty(value = "请填时间格式如(yyyy-MM-dd HH:mm:ss)", required = true)
private String format; @ApiModelProperty(value = "变量信息", required = true)
private List<VariableSearchDTO> variableSearchList;
} }
...@@ -16,26 +16,13 @@ import java.util.List; ...@@ -16,26 +16,13 @@ import java.util.List;
@ApiModel("变量DTO") @ApiModel("变量DTO")
@Data @Data
public class VariableHistoryDataDTO { public class VariableHistoryDataDTO {
// @ApiModelProperty(value = "所属设备", required = true)
// private String deviceId;
@ApiModelProperty(value = "(x轴为变量时,统计类型必填)统计类型,代表(合计值(sum),平均值(avg),最大值(max),最小值(min) 中位数(middle),原值 original)", required = true) @ApiModelProperty(value = "(x轴为变量时,统计类型必填)统计类型,代表(合计值(sum),平均值(avg),最大值(max),最小值(min) 中位数(middle),原值 original)", required = true)
private String statisticsType; private String statisticsType;
// @ApiModelProperty(value = "变量id", required = true)
// private String variableId;
// @ApiModelProperty(value = "变量Code", required = true)
// private String variableCode;
@ApiModelProperty(value = "开始时间(时间戳)",required = true) @ApiModelProperty(value = "开始时间(时间戳)",required = true)
private String startTime; private String startTime;
@ApiModelProperty(value = "结束时间(时间戳)", required = true) @ApiModelProperty(value = "结束时间(时间戳)", required = true)
private String endTime; private String endTime;
@ApiModelProperty(value = "统计维度,如果是时间填time,如果是变量填variableCode", required = true)
private String x;
@ApiModelProperty(value = "统计维度如果是时间,请填时间格式如(yyyy-MM-dd HH:mm:ss),非时间为空", required = true)
private String format;
// @ApiModelProperty(value = "key 为变量id value 为变量名称", required = true)
// private Map<String,String> variables;
@ApiModelProperty(value = "变量信息", required = true) @ApiModelProperty(value = "变量信息", required = true)
private List<VariableSearchDTO> variableSearchList; private List<VariableSearchDTO> variableSearchList;
} }
...@@ -38,9 +38,22 @@ public enum StatisticsType { ...@@ -38,9 +38,22 @@ public enum StatisticsType {
/** /**
* 原值 * 原值
*/ */
ORIGINAL("original"); ORIGINAL("original"),
/**
* 计数
*/
COUNT("count"),
/***
* 去重计数
*/
DUPLICATE_COUNT("duplicate_count");
public String value; public String value;
StatisticsType(String v) { StatisticsType(String v) {
value = v; value = v;
} }
......
...@@ -47,7 +47,7 @@ public interface VariableService { ...@@ -47,7 +47,7 @@ public interface VariableService {
* @param user * @param user
* @return * @return
*/ */
Map<String,List<Map<String,Object>>> getVariableRealTimeDataList(@NonNull String uri,VariableRealTimeDTO variableDTO,CurrentUser user); Map<String,List<Object>> getVariableRealTimeDataList(@NonNull String uri, VariableAllDataDTO variableDTO,CurrentUser user);
/** /**
* 获取历史数据 * 获取历史数据
...@@ -56,7 +56,7 @@ public interface VariableService { ...@@ -56,7 +56,7 @@ public interface VariableService {
* @param currentUser * @param currentUser
* @return * @return
*/ */
List<Map<String,List<Map<String,Object>>>> getVariableHistoryDataList(@NonNull String uri, Map<String,Object> getVariableHistoryDataList(@NonNull String uri,
VariableHistoryDataDTO variableDTO,CurrentUser currentUser); VariableHistoryDataDTO variableDTO,CurrentUser currentUser);
/** /**
...@@ -94,5 +94,5 @@ public interface VariableService { ...@@ -94,5 +94,5 @@ public interface VariableService {
* @param currentUser * @param currentUser
* @return * @return
*/ */
List<Map<String, Object>> getVariableHistoryCurve(VariableHistoryCurveDataDTO variableDTO, CurrentUser currentUser,String uri); // Map<String,List<Map<String,Object>>> getVariableHistoryCurve(VariableHistoryCurveDataDTO variableDTO, CurrentUser currentUser,String uri);
} }
...@@ -23,7 +23,6 @@ import org.springframework.stereotype.Service; ...@@ -23,7 +23,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -119,13 +118,11 @@ public class VariableServiceImpl implements VariableService { ...@@ -119,13 +118,11 @@ public class VariableServiceImpl implements VariableService {
} }
@Override @Override
public Map<String,List<Map<String,Object>>> getVariableRealTimeDataList(@NonNull String uri,VariableRealTimeDTO variableDTO,CurrentUser user) { public Map<String,List<Object>> getVariableRealTimeDataList(@NonNull String uri,
VariableAllDataDTO variableDTO,CurrentUser user) {
if(StringUtils.isBlank(uri)){ if(StringUtils.isBlank(uri)){
throw new SysException("请传入uri"); throw new SysException("请传入uri");
} }
// if(StringUtils.isBlank(variableDTO.getDeviceId())){
// throw new SysException("请传入设备id");
// }
if(CollectionUtils.isEmpty(variableDTO.getVariableSearchList())){ if(CollectionUtils.isEmpty(variableDTO.getVariableSearchList())){
throw new SysException("请传入变量"); throw new SysException("请传入变量");
}else{ }else{
...@@ -145,32 +142,19 @@ public class VariableServiceImpl implements VariableService { ...@@ -145,32 +142,19 @@ public class VariableServiceImpl implements VariableService {
if(StringUtils.isBlank(variableDTO.getStartTime())){ if(StringUtils.isBlank(variableDTO.getStartTime())){
throw new SysException("请传入开始时间"); throw new SysException("请传入开始时间");
} }
if(StringUtils.isBlank(variableDTO.getFormat())) {
throw new SysException(" 请填入时间格式");
}
// Map<String, String> uriVariables =SlmConstants.gson.fromJson(SlmConstants.gson.toJson(variableDTO),new TypeToken<Map<String,String>>(){}.getType()); // Map<String, String> uriVariables =SlmConstants.gson.fromJson(SlmConstants.gson.toJson(variableDTO),new TypeToken<Map<String,String>>(){}.getType());
Map<String, String> uriVariables = Maps.newHashMap(); Map<String, String> uriVariables = Maps.newHashMap();
uriVariables.put("appId",user.getAppId()); uriVariables.put("appId",user.getAppId());
R<Map<String,List<Map<String,Object>>>> result = RestTemplateUtils.post(uri,variableDTO,new TypeToken< R<Map<String,List<Map<String,Object>>>>>() {}.getType(), uriVariables); R<Map<String,List<Object>>> result = RestTemplateUtils.post(uri,variableDTO,new TypeToken<R<Map<String,List<Object>>>>() {}.getType(), uriVariables);
return result.detach(); return result.detach();
} }
@Override @Override
public List<Map<String,List<Map<String,Object>>>> getVariableHistoryDataList(@NonNull String uri, public Map<String,Object> getVariableHistoryDataList(@NonNull String uri,
VariableHistoryDataDTO variableDTO,CurrentUser user) { VariableHistoryDataDTO variableDTO,CurrentUser user) {
if(StringUtils.isBlank(uri)){ if(StringUtils.isBlank(uri)){
throw new SysException("请传入uri"); throw new SysException("请传入uri");
} }
/*if(StringUtils.isBlank(variableDTO.getDeviceId())){
throw new SysException("请传入设备id");
}
if(CollectionUtils.isEmpty(variableDTO.getVariables())){
throw new SysException("请传入变量");
}else{
if(variableDTO.getVariables().values().stream().anyMatch(StringUtils::isBlank)) {
throw new SysException("变量名字不能为空");
}
}*/
if(CollectionUtils.isEmpty(variableDTO.getVariableSearchList())){ if(CollectionUtils.isEmpty(variableDTO.getVariableSearchList())){
throw new SysException("请传入变量"); throw new SysException("请传入变量");
}else{ }else{
...@@ -192,33 +176,25 @@ public class VariableServiceImpl implements VariableService { ...@@ -192,33 +176,25 @@ public class VariableServiceImpl implements VariableService {
throw new SysException("请传入开始时间"); throw new SysException("请传入开始时间");
} }
if(StringUtils.isBlank(variableDTO.getStatisticsType())){
if(StringUtils.isBlank(variableDTO.getX())){
throw new SysException("请传入统计维度");
}
if("time".equals(variableDTO.getX())){
if(StringUtils.isBlank(variableDTO.getFormat())) {
throw new SysException("统计维度为时间,请填入时间格式");
}
}else{
if(StringUtils.isBlank(variableDTO.getStatisticsType())){
throw new SysException("请传入统计类型"); throw new SysException("请传入统计类型");
}else{ }else{
if(!StatisticsType.SUM.value.equals(variableDTO.getStatisticsType()) && if(!StatisticsType.SUM.value.equals(variableDTO.getStatisticsType()) &&
!StatisticsType.AVG.value.equals(variableDTO.getStatisticsType()) && !StatisticsType.AVG.value.equals(variableDTO.getStatisticsType()) &&
!StatisticsType.MAX.value.equals(variableDTO.getStatisticsType()) && !StatisticsType.MAX.value.equals(variableDTO.getStatisticsType()) &&
!StatisticsType.MIN.value.equals(variableDTO.getStatisticsType()) && !StatisticsType.MIN.value.equals(variableDTO.getStatisticsType()) &&
!StatisticsType.MIDDLE.value.equals(variableDTO.getStatisticsType()) && !StatisticsType.MIDDLE.value.equals(variableDTO.getStatisticsType()) &&
!StatisticsType.ORIGINAL.value.equals(variableDTO.getStatisticsType())){ !StatisticsType.ORIGINAL.value.equals(variableDTO.getStatisticsType()) &&
throw new SysException("没有对应匹配的统计类型"); !StatisticsType.COUNT.value.equals(variableDTO.getStatisticsType()) &&
} !StatisticsType.DUPLICATE_COUNT.value.equals(variableDTO.getStatisticsType())){
throw new SysException("没有对应匹配的统计类型");
} }
} }
// Map<String, String> uriVariables =SlmConstants.gson.fromJson(SlmConstants.gson.toJson(variableDTO),new TypeToken<Map<String,String>>(){}.getType()); // Map<String, String> uriVariables =SlmConstants.gson.fromJson(SlmConstants.gson.toJson(variableDTO),new TypeToken<Map<String,String>>(){}.getType());
Map<String, String> uriVariables = Maps.newHashMap(); Map<String, String> uriVariables = Maps.newHashMap();
uriVariables.put("appId",user.getAppId()); uriVariables.put("appId",user.getAppId());
R<List<Map<String,List<Map<String,Object>>>>> result = RestTemplateUtils.post(uri,variableDTO,new TypeToken<R<List<Map<String,List<Map<String,Object>>>>>>() {}.getType(), uriVariables); R<Map<String,Object>> result = RestTemplateUtils.post(uri,variableDTO,new TypeToken<R<Map<String,Object>>>() {}.getType(), uriVariables);
return result.detach(); return result.detach();
} }
...@@ -351,29 +327,36 @@ public class VariableServiceImpl implements VariableService { ...@@ -351,29 +327,36 @@ public class VariableServiceImpl implements VariableService {
return result.detach(); return result.detach();
} }
@Override // @Override
public List<Map<String, Object>> getVariableHistoryCurve(VariableHistoryCurveDataDTO variableDTO, // public Map<String,List<Map<String,Object>>> getVariableHistoryCurve(VariableHistoryCurveDataDTO variableDTO, CurrentUser user,String uri) {
CurrentUser user,String uri) { // if(CollectionUtils.isEmpty(variableDTO.getVariableSearchList())){
if(StringUtils.isBlank(variableDTO.getDeviceId())){ // throw new SysException("请传入变量");
throw new SysException("请传入设备id"); // }else{
} // if(variableDTO.getVariableSearchList().stream().anyMatch(x -> StringUtils.isBlank(x.getDeviceId()))){
if(StringUtils.isBlank(variableDTO.getVariableCode())){ // throw new SysException("设备ID不能为空");
throw new SysException("请传入变量code"); // }
} // if(variableDTO.getVariableSearchList().stream().anyMatch(x -> StringUtils.isBlank(x.getVariableId()))){
if(StringUtils.isBlank(variableDTO.getEndTime())){ // throw new SysException("变量ID不能为空");
throw new SysException("请传入结束时间"); // }
} // if(variableDTO.getVariableSearchList().stream().anyMatch(x -> StringUtils.isBlank(x.getVariableName()))){
if(StringUtils.isBlank(variableDTO.getStartTime())){ // throw new SysException("变量名称不能为空");
throw new SysException("请传入开始时间"); // }
} // }
// if(StringUtils.isBlank(variableDTO.getEndTime())){
// throw new SysException("请传入结束时间");
Map<String, String> uriVariables =SlmConstants.gson.fromJson(SlmConstants.gson.toJson(variableDTO),new TypeToken<Map<String,String>>(){}.getType()); // }
uriVariables.put("appId",user.getAppId()); // if(StringUtils.isBlank(variableDTO.getStartTime())){
// throw new SysException("请传入开始时间");
R<List<Map<String, Object>>> result = RestTemplateUtils.get(uri, new TypeToken<R<List<Map<String, Object>>>>() {}.getType(), uriVariables); // }
return result.detach(); //
} //
// //Map<String, String> uriVariables =SlmConstants.gson.fromJson(SlmConstants.gson.toJson(variableDTO),new TypeToken<Map<String,String>>(){}.getType());
// Map<String, String> uriVariables = Maps.newHashMap();
// uriVariables.put("appId",user.getAppId());
//
// R<Map<String,List<Map<String,Object>>>> result = RestTemplateUtils.post(uri,variableDTO,new TypeToken<R<Map<String,List<Map<String,Object>>>>>() {}.getType(), uriVariables);
// return result.detach();
// }
private R<Map<String,String>> setDeptAndRole(CurrentUser user,String uri){ private R<Map<String,String>> setDeptAndRole(CurrentUser user,String uri){
Map<String,String> uriVariables =Maps.newHashMap(); Map<String,String> uriVariables =Maps.newHashMap();
......
...@@ -60,11 +60,12 @@ dc_client: ...@@ -60,11 +60,12 @@ dc_client:
businessFiledData : /{appId}/business/filed businessFiledData : /{appId}/business/filed
# variableHistoryDataList: /{appId}/variables/history?deviceId={deviceId}&endTime={endTime}&startTime={startTime}&statisticsType={statisticsType}&variableCode={variableCode}&variableId={variableId}&x={x}&format={format} # variableHistoryDataList: /{appId}/variables/history?deviceId={deviceId}&endTime={endTime}&startTime={startTime}&statisticsType={statisticsType}&variableCode={variableCode}&variableId={variableId}&x={x}&format={format}
# variableRealTimeDataList: /{appId}/variables/real-time?deviceId={deviceId}&endTime={endTime}&startTime={startTime}&variableCode={variableCode}&variableId={variableId}&format={format} # variableRealTimeDataList: /{appId}/variables/real-time?deviceId={deviceId}&endTime={endTime}&startTime={startTime}&variableCode={variableCode}&variableId={variableId}&format={format}
variableHistoryDataList: /{appId}/variables/history variableCodeHistoryList: /{appId}/variables/variableCode/history
variableRealTimeDataList: /{appId}/variables/real-time variableAllDataList: /{appId}/variables/all/data
filedValue : /{appId}/business/{tableName}/{filed}/filed-value?current={current}&size={size}&name={name} #/{appId}/business/{tableName}/{filed}/filed-value?current={current}&size={size}&name={name} filedValue : /{appId}/business/{tableName}/{filed}/filed-value?current={current}&size={size}&name={name} #/{appId}/business/{tableName}/{filed}/filed-value?current={current}&size={size}&name={name}
send : /{appId}/variables/monitor/device/commands send : /{appId}/variables/monitor/device/commands
variableStatus : /{appId}/variables/{deviceId}/{variableCode}/status variableStatus : /{appId}/variables/{deviceId}/{variableCode}/status
variableHistoryStatus : /{appId}/variables/{deviceId}/{variableCode}/history-status?startTime={startTime}&endTime={endTime} variableHistoryStatus : /{appId}/variables/{deviceId}/{variableCode}/history-status?startTime={startTime}&endTime={endTime}
historyCurve : /{appId}/variables/history-curve?deviceId={deviceId}&endTime={endTime}&startTime={startTime}&variableCode={variableCode}&variableId={variableId}&format={format} # historyCurve : /{appId}/variables/history-curve?deviceId={deviceId}&endTime={endTime}&startTime={startTime}&variableCode={variableCode}&variableId={variableId}&format={format}
# historyCurve : /{appId}/variables/history-curve
permissionCodeUrl : /{appId}/bi/permission/code permissionCodeUrl : /{appId}/bi/permission/code
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment