225 lines
5.9 KiB
Python
225 lines
5.9 KiB
Python
import random
|
|
from django.db import models
|
|
from django.utils.timezone import now, localtime
|
|
import datetime
|
|
from utils import const
|
|
import utils
|
|
|
|
class Recipe(models.Model):
|
|
name = models.CharField(max_length=128)
|
|
recipe_type = models.CharField(max_length=32,
|
|
default=const.RECIPE_TYPE_MEAT)
|
|
note = models.TextField(null=True)
|
|
rate = models.IntegerField(default=0)
|
|
difficulty = models.IntegerField(default=0)
|
|
|
|
def serialize(self, verbose=False):
|
|
data = {
|
|
'id': self.id,
|
|
'name': self.name,
|
|
'recipe_type': self.recipe_type,
|
|
}
|
|
if verbose:
|
|
data.update({
|
|
'difficulty': self.difficulty,
|
|
'rate': self.rate,
|
|
'note': self.note,
|
|
})
|
|
|
|
return data
|
|
|
|
@classmethod
|
|
def create_from_str(cls, content):
|
|
content = content.strip()
|
|
if not content:
|
|
return
|
|
name, *data = content.split(' ')
|
|
recipe_type = rate = difficulty = None
|
|
keys = [recipe_type, rate, difficulty]
|
|
for x in range(len(data)):
|
|
keys[x] = data[x]
|
|
recipe_type, rate, difficulty = keys
|
|
|
|
if recipe_type == '肉':
|
|
recipe_type = const.RECIPE_TYPE_MEAT
|
|
elif recipe_type == '菜':
|
|
recipe_type = const.RECIPE_TYPE_VEGETABLE
|
|
elif recipe_type == '汤':
|
|
recipe_type = const.RECIPE_TYPE_SOUP
|
|
else:
|
|
recipe_type = const.RECIPE_TYPE_MEAT
|
|
if rate:
|
|
try:
|
|
rate = int(rate)
|
|
except:
|
|
rate = 0
|
|
else:
|
|
rate = 0
|
|
if difficulty:
|
|
try:
|
|
difficulty = int(difficulty)
|
|
except:
|
|
difficulty = 0
|
|
else:
|
|
difficulty = 0
|
|
recipe = cls.objects.create(
|
|
name=name,
|
|
recipe_type=recipe_type,
|
|
rate=rate,
|
|
difficulty=difficulty
|
|
)
|
|
return recipe
|
|
|
|
@property
|
|
def display_recipe_type(self):
|
|
if self.recipe_type == const.RECIPE_TYPE_VEGETABLE:
|
|
return '菜'
|
|
elif self.recipe_type == const.RECIPE_TYPE_MEAT:
|
|
return '肉'
|
|
elif self.recipe_type == const.RECIPE_TYPE_SOUP:
|
|
return '汤'
|
|
return '肉'
|
|
|
|
@property
|
|
def display_rate(self):
|
|
return '🍚' * self.rate
|
|
|
|
@property
|
|
def display_difficult(self):
|
|
return '⭐️' * self.difficulty
|
|
|
|
def construct_lart_card(self):
|
|
|
|
data = {
|
|
"config": {
|
|
"wide_screen_mode": True
|
|
},
|
|
"elements": [
|
|
{
|
|
"tag": "markdown",
|
|
"content": "# **%s**\n类型:%s\n评分:%s\n难度:%s" % (
|
|
self.name, self.display_recipe_type, self.display_rate,
|
|
self.display_difficult)
|
|
},
|
|
{
|
|
"tag": "action",
|
|
"actions": [
|
|
{
|
|
"tag": "button",
|
|
"text": {
|
|
"tag": "plain_text",
|
|
"content": "查看"
|
|
},
|
|
"multi_url": {
|
|
"url": "https://recipe.tunpok.com/recipe/%s" % self.id,
|
|
"android_url": "https://recipe.tunpok.com/recipe-mobile/recipe/%s" % self.id,
|
|
"ios_url": "https://recipe.tunpok.com/recipe-mobile/recipe/%s" % self.id,
|
|
"pc_url": "https://recipe.tunpok.com/recipe/%s" % self.id
|
|
},
|
|
"type": "primary"
|
|
},
|
|
{
|
|
"tag": "button",
|
|
"text": {
|
|
"tag": "plain_text",
|
|
"content": "删除"
|
|
},
|
|
"type": "danger"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
return data
|
|
|
|
|
|
class DailyRecipe(models.Model):
|
|
recipes = models.ManyToManyField(Recipe)
|
|
date = models.DateField()
|
|
meal_type = models.CharField(
|
|
max_length=32,
|
|
default=const.DAILY_RECIPE_MEAL_TYPE_SUPPER,)
|
|
|
|
def generate_recipe(self, prev_recipes=None, ignore_prev=False):
|
|
if not prev_recipes:
|
|
prev_recipes = []
|
|
if ignore_prev:
|
|
prev_recipes = []
|
|
|
|
recipes = []
|
|
retry = 5
|
|
|
|
# meat
|
|
for x in range(0,2):
|
|
while True:
|
|
recipe = Recipe.objects.filter(
|
|
recipe_type=const.RECIPE_TYPE_MEAT,
|
|
).order_by('?').first()
|
|
if recipe and recipe.id not in recipes and recipe.id not in prev_recipes:
|
|
recipes.append(recipe.id)
|
|
break
|
|
else:
|
|
retry -= 1
|
|
if retry <= 0:
|
|
retry = 5
|
|
break
|
|
|
|
# vegetable
|
|
for x in range(0, 1):
|
|
while True:
|
|
recipe = Recipe.objects.filter(
|
|
recipe_type=const.RECIPE_TYPE_VEGETABLE,
|
|
).order_by('?').first()
|
|
if recipe and recipe.id not in recipes and recipe.id not in prev_recipes:
|
|
recipes.append(recipe.id)
|
|
break
|
|
else:
|
|
retry -= 1
|
|
if retry <= 0:
|
|
retry = 5
|
|
break
|
|
|
|
# soup
|
|
if random.randint(0,2):
|
|
recipe = Recipe.objects.filter(
|
|
recipe_type=const.RECIPE_TYPE_SOUP,
|
|
).order_by('?').first()
|
|
# if recipe not in recipes and recipe not in prev_recipes:
|
|
if recipe:
|
|
recipes.append(recipe.id)
|
|
|
|
self.recipes.set(Recipe.objects.filter(id__in=recipes))
|
|
|
|
def serialize(self):
|
|
data = {
|
|
const.RECIPE_TYPE_MEAT: [],
|
|
const.RECIPE_TYPE_VEGETABLE: [],
|
|
const.RECIPE_TYPE_SOUP: [],
|
|
}
|
|
for key_, value_ in data.items():
|
|
for recipe in self.recipes.filter(
|
|
recipe_type=key_).order_by('id'):
|
|
value_.append(recipe.serialize())
|
|
|
|
date = now()
|
|
date = date.replace(year=self.date.year, month=self.date.month,
|
|
day=self.date.day, hour=0, minute=0)
|
|
data['date'] = utils.timestamp_of(utils.day_start(date))
|
|
data['id'] = self.id
|
|
return data
|
|
|
|
@classmethod
|
|
def get_week_recipe_data(cls):
|
|
today = localtime()
|
|
week_start = (today - datetime.timedelta(days=today.weekday())).date()
|
|
week_end = week_start + datetime.timedelta(days=6)
|
|
daily_recipes = cls.objects.filter(
|
|
date__gte=week_start,
|
|
date__lte=week_end,
|
|
).order_by('date')
|
|
data = [{}] * (7 - len(daily_recipes))
|
|
|
|
for daily_recipe in daily_recipes:
|
|
data.append(daily_recipe.serialize())
|
|
return data
|