17 changed files with 1070 additions and 946 deletions
@ -0,0 +1,213 @@ |
|||
package com.mathvision.diet.service; |
|||
|
|||
import com.alibaba.fastjson2.JSONArray; |
|||
import com.alibaba.fastjson2.JSONObject; |
|||
import com.google.common.collect.Lists; |
|||
import com.google.common.collect.Maps; |
|||
import com.google.common.collect.Range; |
|||
import com.mathvision.diet.domian.MenuDishItemDTO; |
|||
import com.mathvision.diet.entity.*; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.collections4.CollectionUtils; |
|||
import org.apache.commons.lang3.tuple.Pair; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.math.BigDecimal; |
|||
import java.math.RoundingMode; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class MenuReportService { |
|||
@Resource |
|||
EnumService enumService; |
|||
|
|||
@Resource |
|||
NutritionService nutritionService; |
|||
|
|||
@Resource |
|||
IngredientService ingredientService; |
|||
|
|||
public JSONObject assess(Menu menu, long day, String crow, List<MenuDish> dishes) { |
|||
Nutrition nutrition = nutritionService.get(menu.getNutrient()); |
|||
BigDecimal overflow = nutrition.getOverflow(); |
|||
Map<String, Map<String, BigDecimal>> itemStandard = nutrition.getIngredient().getOrDefault(crow, new HashMap<>()); |
|||
Map<String, Ingredient> ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(MenuDishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); |
|||
Map<String, BigDecimal> items = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> item.getValue().containsKey(crow) && item.getValue().get(crow).doubleValue() > 0 && ingredientMap.containsKey(item.getKey()))).flatMap(x -> ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue().get(crow)).divide(new BigDecimal(100), RoundingMode.HALF_UP)))).collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); |
|||
Map<String, Integer> types = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> ingredientMap.get(item.getKey()).getType())).collect(Collectors.toMap(x -> x, x -> 1, Integer::sum)); |
|||
|
|||
JSONObject result = new JSONObject(); |
|||
result.put("day", day); |
|||
result.put("crow", crow); |
|||
result.put("meals", dishes.stream().map(MenuDish::getMeal).collect(Collectors.toSet())); |
|||
result.put("types", types); |
|||
|
|||
JSONArray contents = new JSONArray(); |
|||
items.forEach((key, value) -> { |
|||
FoodNutrient foodNutrient = enumService.getNutrient(key); |
|||
|
|||
if (foodNutrient == null) { |
|||
return; |
|||
} |
|||
JSONObject content = new JSONObject(); |
|||
content.put("nutrition", String.format("%s/%s", foodNutrient.getValue(), foodNutrient.getMeasurement())); |
|||
content.put("virtual", value); |
|||
|
|||
Map<String, BigDecimal> standard = itemStandard.get(key); |
|||
BigDecimal max = standard == null ? null : standard.get("max"); |
|||
BigDecimal min = standard == null ? null : standard.get("min"); |
|||
BigDecimal ul = standard == null ? null : standard.get("ul"); |
|||
if (max == null) { |
|||
if (min == null) { |
|||
content.put("standard", "-"); |
|||
content.put("ul", ul == null ? "-" : ul.toString()); |
|||
content.put("overload", "-"); |
|||
content.put("conclusion", "-"); |
|||
} else { |
|||
content.put("standard", "≥" + min); |
|||
content.put("ul", ul == null ? "-" : ul.toString()); |
|||
if (min.compareTo(value) > 0) { |
|||
content.put("overload", value.subtract(min).divide(min, RoundingMode.FLOOR)); |
|||
if(min.subtract(value).compareTo(overflow.divide(new BigDecimal(100), RoundingMode.FLOOR).multiply(value)) > 0) { |
|||
content.put("conclusion", "不足"); |
|||
} else { |
|||
content.put("conclusion", "适量"); |
|||
} |
|||
} else { |
|||
content.put("overload", BigDecimal.ZERO); |
|||
content.put("conclusion", "适量"); |
|||
} |
|||
} |
|||
} else { |
|||
if (min == null) { |
|||
content.put("standard", "≤" + max); |
|||
content.put("ul", ul == null ? "-" : ul.toString()); |
|||
if (max.compareTo(value) < 0) { |
|||
if(value.subtract(max).compareTo(overflow.divide(new BigDecimal(100), RoundingMode.FLOOR).multiply(value)) > 0) { |
|||
if(ul != null && value.compareTo(ul) > 0) { |
|||
content.put("conclusion", "严重超标"); |
|||
} else { |
|||
content.put("conclusion", "超量"); |
|||
} |
|||
} else { |
|||
content.put("conclusion", "适量"); |
|||
} |
|||
content.put("overload", value.subtract(max).divide(max, RoundingMode.FLOOR)); |
|||
} else { |
|||
content.put("overload", BigDecimal.ZERO); |
|||
} |
|||
} else { |
|||
content.put("standard", min + "~" + max); |
|||
content.put("ul", ul == null ? "-" : ul.toString()); |
|||
if (min.compareTo(value) > 0) { |
|||
content.put("overload", value.subtract(min).divide(min, RoundingMode.FLOOR)); |
|||
if(min.subtract(value).compareTo(overflow.divide(new BigDecimal(100), RoundingMode.FLOOR).multiply(value)) > 0) { |
|||
content.put("conclusion", "不足"); |
|||
} else { |
|||
content.put("conclusion", "适量"); |
|||
} |
|||
} else { |
|||
if (max.compareTo(value) < 0) { |
|||
content.put("overload", value.subtract(max).divide(max, RoundingMode.FLOOR)); |
|||
if(value.subtract(max).compareTo(overflow.divide(new BigDecimal(100), RoundingMode.FLOOR).multiply(value)) > 0) { |
|||
if(ul != null && value.compareTo(ul) > 0) { |
|||
content.put("conclusion", "严重超标"); |
|||
} else { |
|||
content.put("conclusion", "超量"); |
|||
} |
|||
} else { |
|||
content.put("conclusion", "适量"); |
|||
} |
|||
} else { |
|||
content.put("overload", "0%"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
contents.add(content); |
|||
}); |
|||
result.put("ingredient", contents); |
|||
return result; |
|||
} |
|||
|
|||
public JSONObject types(Menu menu, List<MenuDish> dishes) { |
|||
Nutrition nutrition = nutritionService.get(menu.getNutrient()); |
|||
Map<String, BigDecimal> dayStandard = nutrition.getFoodCategoryDay(); |
|||
Map<String, BigDecimal> weekStandard = nutrition.getFoodCategoryWeek(); |
|||
Map<String, Ingredient> ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(MenuDishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); |
|||
Map<Pair<Long, String>, Integer> typesDay = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> Pair.of(dish.getDay(), ingredientMap.get(item.getKey()).getType()))).collect(Collectors.toMap(x -> x, x -> 1, Integer::sum)); |
|||
JSONArray dayRule = new JSONArray(); |
|||
Map<Long, JSONArray> dayMaps = Maps.newHashMap(); |
|||
typesDay.forEach((key, num) -> { |
|||
Long day = key.getKey(); |
|||
JSONArray dayCollection = dayMaps.getOrDefault(day, new JSONArray()); |
|||
String type = key.getValue(); |
|||
int standard = dayStandard.getOrDefault(type, BigDecimal.ZERO).intValue(); |
|||
JSONObject content = new JSONObject(); |
|||
content.put("day", day); |
|||
content.put("name", type); |
|||
content.put("standard", standard); |
|||
content.put("supplied", num); |
|||
content.put("lack", num >= standard ? 0 : standard - num); |
|||
dayCollection.add(content); |
|||
dayMaps.put(day, dayCollection); |
|||
}); |
|||
dayRule.addAll(dayMaps.values()); |
|||
|
|||
Map<String, Integer> typesAll = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> ingredientMap.get(item.getKey()).getType())).collect(Collectors.toMap(x -> x, x -> 1, Integer::sum)); |
|||
JSONArray weekRule = new JSONArray(); |
|||
typesAll.forEach((type, num) -> { |
|||
BigDecimal standard = weekStandard.getOrDefault(type, BigDecimal.ZERO); |
|||
JSONObject content = new JSONObject(); |
|||
content.put("name", type); |
|||
content.put("standard", standard); |
|||
content.put("supplied", num); |
|||
content.put("lack", num.compareTo(standard.intValue()) > 0 ? 0 : standard.intValue() - num); |
|||
weekRule.add(content); |
|||
}); |
|||
|
|||
JSONObject result = new JSONObject(); |
|||
result.put("dayRule", dayRule); |
|||
result.put("weekRule", weekRule); |
|||
return result; |
|||
} |
|||
|
|||
public JSONObject energy(long day, String crow, List<MenuDish> dishes) { |
|||
List<String> allConcerned= Lists.newArrayList("energy", "protein", "fat", "carbs"); |
|||
Map<String, Ingredient> ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(MenuDishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); |
|||
Map<String, BigDecimal> items = dishes.stream() |
|||
.flatMap(dish -> dish.getIngredient().stream().filter(item -> item.getValue().containsKey(crow) && item.getValue().get(crow).doubleValue() > 0 && ingredientMap.containsKey(item.getKey()))) |
|||
.flatMap(x -> ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue().get(crow)).divide(new BigDecimal(100), RoundingMode.HALF_UP)))) |
|||
.filter(x -> allConcerned.contains(x.getKey())) |
|||
.collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); |
|||
|
|||
JSONObject result = new JSONObject(); |
|||
result.put("day", day); |
|||
result.put("crow", crow); |
|||
result.put("meals", dishes.stream().map(MenuDish::getMeal).collect(Collectors.toSet())); |
|||
|
|||
BigDecimal energy = items.get("energy"); |
|||
if (energy == null || energy.doubleValue() <= 0) { |
|||
return result; |
|||
} |
|||
JSONArray contents = new JSONArray(); |
|||
contents.add(toEnergyContent(energy, "protein", Range.closed(10, 20), items, ingredientMap)); |
|||
contents.add(toEnergyContent(energy, "fat", Range.closed(20, 30), items, ingredientMap)); |
|||
contents.add(toEnergyContent(energy, "carbs", Range.closed(50, 60), items, ingredientMap)); |
|||
result.put("energy", contents); |
|||
return result; |
|||
} |
|||
|
|||
private JSONObject toEnergyContent(BigDecimal energy, String key, Range<Integer> standard, Map<String, BigDecimal> items, Map<String, Ingredient> ingredientMap) { |
|||
double value = items.getOrDefault(key, BigDecimal.ZERO).divide(energy, RoundingMode.FLOOR).multiply(new BigDecimal(100)).doubleValue(); |
|||
JSONObject result = JSONObject.of("name", enumService.getNutrient(key).getValue() + "/总能量"); |
|||
result.put("standard", String.format("%s~%s", standard.lowerEndpoint(), standard.upperEndpoint())); |
|||
result.put("value", value); |
|||
result.put("conclusion", standard.lowerEndpoint() > value ? "略低" : standard.upperEndpoint() < value ? "略高" : "合适"); |
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
package com.mathvision.diet.controller; |
|||
|
|||
import com.alibaba.fastjson2.JSONObject; |
|||
import com.mathvision.diet.entity.Menu; |
|||
import com.mathvision.diet.entity.MenuDish; |
|||
import com.mathvision.diet.service.MenuDishService; |
|||
import com.mathvision.diet.service.MenuReportService; |
|||
import com.mathvision.diet.service.MenuService; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.util.Assert; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestMethod; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.time.LocalDate; |
|||
import java.util.List; |
|||
|
|||
@RequestMapping("/api/menu/analysis") |
|||
@Controller |
|||
public class MenuReportController extends BaseController { |
|||
|
|||
@Resource |
|||
MenuService menuService; |
|||
|
|||
@Resource |
|||
MenuDishService menuDishService; |
|||
|
|||
@Resource |
|||
MenuReportService menuReportService; |
|||
|
|||
@ResponseBody |
|||
@RequestMapping(method = RequestMethod.GET) |
|||
public JSONObject analysis(@RequestParam Long id, @RequestParam(required = false) Long day, @RequestParam(required = false) String crow) { |
|||
Menu menu = checkAndGetMenu(id); |
|||
day = checkAndGetDay(day, menu.getDay()); |
|||
crow = checkAndGetCrow(crow, menu.getCrows()); |
|||
List<MenuDish> dishes = menuDishService.query(id, menu.getVender(), day); |
|||
return menuReportService.assess(menu, day, crow, dishes); |
|||
} |
|||
|
|||
@ResponseBody |
|||
@RequestMapping(value = "types", method = RequestMethod.GET) |
|||
public JSONObject types(@RequestParam Long id) { |
|||
Menu menu = checkAndGetMenu(id); |
|||
List<MenuDish> dishes = menuDishService.query(id, menu.getVender()); |
|||
return menuReportService.types(menu, dishes); |
|||
} |
|||
|
|||
@ResponseBody |
|||
@RequestMapping(value = "energy", method = RequestMethod.GET) |
|||
public JSONObject energy(@RequestParam Long id, @RequestParam(required = false) Long day, @RequestParam(required = false) String crow) { |
|||
Menu menu = checkAndGetMenu(id); |
|||
day = checkAndGetDay(day, menu.getDay()); |
|||
crow = checkAndGetCrow(crow, menu.getCrows()); |
|||
List<MenuDish> dishes = menuDishService.query(id, menu.getVender(), day); |
|||
return menuReportService.energy(day, crow, dishes); |
|||
} |
|||
|
|||
private Menu checkAndGetMenu(Long id) { |
|||
Menu menu = isAdmin() ? menuService.get(id) : menuService.get(id, getVender()); |
|||
Assert.notNull(menu, "[参数错误]食谱不存在!"); |
|||
return menu; |
|||
} |
|||
|
|||
private Long checkAndGetDay(Long day, Long defaultDay) { |
|||
return (day == null || day < 1 || day > defaultDay) ? (long) LocalDate.now().getDayOfWeek().getValue() : day; |
|||
} |
|||
|
|||
private String checkAndGetCrow(String crow, List<String> allCrow) { |
|||
return StringUtils.isBlank(crow) || !allCrow.contains(crow) ? allCrow.get(0) : crow; |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
package com.mathvision.diet.domain; |
|||
|
|||
public class Session { |
|||
private static final ThreadLocal<UserDO> SESSION = new ThreadLocal<>(); |
|||
|
|||
public static UserDO get() { |
|||
return SESSION.get(); |
|||
} |
|||
|
|||
public static void set(UserDO userDO) { |
|||
SESSION.set(userDO); |
|||
} |
|||
|
|||
public static void clear() { |
|||
SESSION.remove(); |
|||
} |
|||
} |
|||
@ -1 +1,354 @@ |
|||
<h1>1. 食谱分析</h1> |
|||
<blockquote> |
|||
<p>GET /api/menu/analysis</p> |
|||
</blockquote> |
|||
<h3>输入:</h3> |
|||
<pre><code class="text">id=1 // 食谱ID, 必填 |
|||
day=3 // 那一天, 默认当天 |
|||
crow=xxx //人群,默认第一个人群 |
|||
</code></pre> |
|||
<h3>输出:</h3> |
|||
<pre><code class="json">{ |
|||
"body": { |
|||
"day": 5, |
|||
"crow": "10", |
|||
"meals": [ |
|||
"早餐" |
|||
], |
|||
"types": { |
|||
"蛋类": 5, |
|||
"鱼虾类": 2, |
|||
"调味品": 1 |
|||
}, |
|||
"ingredient": [ |
|||
{ |
|||
"nutrition": "膳食纤维/g", |
|||
"virtual": 0, |
|||
"standard": "1~2", |
|||
"ul": "-", |
|||
"overload": -1, |
|||
"conclusion": "不足" |
|||
}, |
|||
{ |
|||
"nutrition": "钙/mg", |
|||
"virtual": 2, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "维生素B1/mg", |
|||
"virtual": 1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "碳水化合物/g", |
|||
"virtual": 0.1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "蛋白质/g", |
|||
"virtual": 0.1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "维生素B2/mg", |
|||
"virtual": 2, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "脂肪/g", |
|||
"virtual": 0.0, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "铁/mg", |
|||
"virtual": 0.1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "维生素A/μgRAE", |
|||
"virtual": 4, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "能量kcal/kcal", |
|||
"virtual": 0.79, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
} |
|||
] |
|||
}, |
|||
"code": 200, |
|||
"desc": "成功", |
|||
"success": true |
|||
} |
|||
</code></pre> |
|||
<h1>2. 食谱分析</h1> |
|||
<blockquote> |
|||
<p>GET /api/menu/analysis/energy</p> |
|||
</blockquote> |
|||
<h3>输入:</h3> |
|||
<pre><code class="text">id=1 // 食谱ID, 必填 |
|||
day=3 // 那一天, 默认当天 |
|||
crow=xxx //人群,默认第一个人群 |
|||
</code></pre> |
|||
<h3>输出:</h3> |
|||
<pre><code class="json">{ |
|||
"body": { |
|||
"day": 5, |
|||
"crow": "10", |
|||
"meals": [ |
|||
"早餐" |
|||
], |
|||
"energy": [ |
|||
{ |
|||
"name": "蛋白质/总能量", |
|||
"standard": "10~20", |
|||
"value": 10.0, |
|||
"conclusion": "合适" |
|||
}, |
|||
{ |
|||
"name": "脂肪/总能量", |
|||
"standard": "20~30", |
|||
"value": 0.0, |
|||
"conclusion": "略低" |
|||
}, |
|||
{ |
|||
"name": "碳水化合物/总能量", |
|||
"standard": "50~60", |
|||
"value": 10.0, |
|||
"conclusion": "略低" |
|||
} |
|||
] |
|||
}, |
|||
"code": 200, |
|||
"desc": "成功", |
|||
"success": true |
|||
} |
|||
</code></pre> |
|||
<h1>3. 食谱分析</h1> |
|||
<blockquote> |
|||
<p>GET /api/menu/analysis/types</p> |
|||
</blockquote> |
|||
<h3>输入:</h3> |
|||
<pre><code class="text">id=1 // 食谱ID, 必填 |
|||
crow=xxx //人群,默认第一个人群 |
|||
</code></pre> |
|||
<h3>输出:</h3> |
|||
<pre><code class="json">{ |
|||
"body": { |
|||
"dayRule": [ |
|||
[ |
|||
{ |
|||
"day": 1, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 1, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 1, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 2, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 2, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 2, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 3, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 3, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 3, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 4, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 4, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 4, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 5, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 5, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 5, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 6, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 6, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 6, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 7, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 7, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 7, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
] |
|||
], |
|||
"weekRule": [ |
|||
{ |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 35, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 14, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 7, |
|||
"lack": 0 |
|||
} |
|||
] |
|||
}, |
|||
"code": 200, |
|||
"desc": "成功", |
|||
"success": true |
|||
} |
|||
</code></pre> |
|||
|
|||
|
|||
@ -0,0 +1,366 @@ |
|||
# 1. 食谱分析 |
|||
|
|||
|
|||
> GET /api/menu/analysis |
|||
|
|||
### 输入: |
|||
```text |
|||
id=1 // 食谱ID, 必填 |
|||
day=3 // 那一天, 默认当天 |
|||
crow=xxx //人群,默认第一个人群 |
|||
``` |
|||
|
|||
### 输出: |
|||
~~~json |
|||
{ |
|||
"body": { |
|||
"day": 5, |
|||
"crow": "10", |
|||
"meals": [ |
|||
"早餐" |
|||
], |
|||
"types": { |
|||
"蛋类": 5, |
|||
"鱼虾类": 2, |
|||
"调味品": 1 |
|||
}, |
|||
"ingredient": [ |
|||
{ |
|||
"nutrition": "膳食纤维/g", |
|||
"virtual": 0, |
|||
"standard": "1~2", |
|||
"ul": "-", |
|||
"overload": -1, |
|||
"conclusion": "不足" |
|||
}, |
|||
{ |
|||
"nutrition": "钙/mg", |
|||
"virtual": 2, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "维生素B1/mg", |
|||
"virtual": 1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "碳水化合物/g", |
|||
"virtual": 0.1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "蛋白质/g", |
|||
"virtual": 0.1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "维生素B2/mg", |
|||
"virtual": 2, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "脂肪/g", |
|||
"virtual": 0.0, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "铁/mg", |
|||
"virtual": 0.1, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "维生素A/μgRAE", |
|||
"virtual": 4, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
}, |
|||
{ |
|||
"nutrition": "能量kcal/kcal", |
|||
"virtual": 0.79, |
|||
"standard": "-", |
|||
"ul": "-", |
|||
"overload": "-", |
|||
"conclusion": "-" |
|||
} |
|||
] |
|||
}, |
|||
"code": 200, |
|||
"desc": "成功", |
|||
"success": true |
|||
} |
|||
~~~ |
|||
|
|||
|
|||
# 2. 食谱分析 |
|||
|
|||
> GET /api/menu/analysis/energy |
|||
|
|||
### 输入: |
|||
```text |
|||
id=1 // 食谱ID, 必填 |
|||
day=3 // 那一天, 默认当天 |
|||
crow=xxx //人群,默认第一个人群 |
|||
``` |
|||
|
|||
### 输出: |
|||
~~~json |
|||
{ |
|||
"body": { |
|||
"day": 5, |
|||
"crow": "10", |
|||
"meals": [ |
|||
"早餐" |
|||
], |
|||
"energy": [ |
|||
{ |
|||
"name": "蛋白质/总能量", |
|||
"standard": "10~20", |
|||
"value": 10.0, |
|||
"conclusion": "合适" |
|||
}, |
|||
{ |
|||
"name": "脂肪/总能量", |
|||
"standard": "20~30", |
|||
"value": 0.0, |
|||
"conclusion": "略低" |
|||
}, |
|||
{ |
|||
"name": "碳水化合物/总能量", |
|||
"standard": "50~60", |
|||
"value": 10.0, |
|||
"conclusion": "略低" |
|||
} |
|||
] |
|||
}, |
|||
"code": 200, |
|||
"desc": "成功", |
|||
"success": true |
|||
} |
|||
~~~ |
|||
|
|||
# 3. 食谱分析 |
|||
|
|||
> GET /api/menu/analysis/types |
|||
|
|||
### 输入: |
|||
```text |
|||
id=1 // 食谱ID, 必填 |
|||
crow=xxx //人群,默认第一个人群 |
|||
``` |
|||
|
|||
### 输出: |
|||
~~~json |
|||
{ |
|||
"body": { |
|||
"dayRule": [ |
|||
[ |
|||
{ |
|||
"day": 1, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 1, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 1, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 2, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 2, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 2, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 3, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 3, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 3, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 4, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 4, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 4, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 5, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 5, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 5, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 6, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 6, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 6, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"day": 7, |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 2, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 7, |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 5, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"day": 7, |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 1, |
|||
"lack": 0 |
|||
} |
|||
] |
|||
], |
|||
"weekRule": [ |
|||
{ |
|||
"name": "蛋类", |
|||
"standard": 0, |
|||
"supplied": 35, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"name": "鱼虾类", |
|||
"standard": 0, |
|||
"supplied": 14, |
|||
"lack": 0 |
|||
}, |
|||
{ |
|||
"name": "调味品", |
|||
"standard": 0, |
|||
"supplied": 7, |
|||
"lack": 0 |
|||
} |
|||
] |
|||
}, |
|||
"code": 200, |
|||
"desc": "成功", |
|||
"success": true |
|||
} |
|||
~~~ |
|||
Loading…
Reference in new issue