mybuddy/babybuddy/management/commands/fake.py

380 lines
12 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2022-04-04 01:13:25 +00:00
from random import choice, choices, randint, uniform
from datetime import timedelta
from decimal import Decimal
from django.db import transaction
2022-04-04 01:13:25 +00:00
from django.db.utils import IntegrityError
from django.core.management.base import BaseCommand
from django.utils import timezone
2022-05-28 02:56:38 +00:00
from faker import Faker
2017-11-10 02:15:09 +00:00
from core import models
class Command(BaseCommand):
2022-02-10 00:00:30 +00:00
help = "Generates fake children and related entries."
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
2022-05-28 02:56:38 +00:00
self.faker = Faker()
self.child = None
self.weight = None
2022-04-04 01:13:25 +00:00
self.tags = []
self.time = None
self.time_now = timezone.localtime()
def add_arguments(self, parser):
parser.add_argument(
2022-02-10 00:00:30 +00:00
"--children",
dest="children",
default=1,
2022-02-10 00:00:30 +00:00
help="The number of fake children to create.",
)
parser.add_argument(
2022-02-10 00:00:30 +00:00
"--days",
dest="days",
2017-10-21 22:54:24 +00:00
default=31,
2022-02-10 00:00:30 +00:00
help="How many days of fake entries to create.",
)
def handle(self, *args, **kwargs):
2022-02-10 00:00:30 +00:00
verbosity = int(kwargs["verbosity"])
children = int(kwargs["children"]) or 1
days = int(kwargs["days"]) or 31
for i in range(0, 10):
text = self.faker.password(randint(4, 10))
2022-04-04 01:13:25 +00:00
try:
tag = models.Tag.objects.create(name=text)
2022-04-04 01:13:25 +00:00
tag.save()
self.tags.append(tag)
except IntegrityError:
pass
2022-02-10 00:00:30 +00:00
birth_date = timezone.localtime() - timedelta(days=days)
for i in range(0, children):
self.child = models.Child.objects.create(
first_name=self.faker.first_name(),
last_name=self.faker.last_name(),
2022-02-10 00:00:30 +00:00
birth_date=birth_date,
)
self.child.save()
self._add_child_data()
if verbosity > 0:
2022-02-10 00:00:30 +00:00
self.stdout.write(self.style.SUCCESS("Successfully added fake data."))
@transaction.atomic
def _add_child_data(self):
"""
Adds fake data for child from child.birth_date to now. The fake data
follows a semi-regular pattern of sleep, feed, change, tummy time,
change, tummy time, sleep, etc.
:returns:
"""
self.time = self.child.birth_date
2019-05-17 04:33:26 +00:00
2022-03-04 15:39:13 +00:00
self.pumping = round(uniform(95.0, 102.0), 2)
self._add_pumping_entry()
2019-05-17 04:33:26 +00:00
self.temperature = round(uniform(95.0, 102.0), 2)
self._add_temperature_entry()
self.weight = round(uniform(8.0, 12.0), 2)
self._add_weight_entry()
2019-05-17 04:33:26 +00:00
last_weight_entry_time = self.time
2021-12-30 03:32:55 +00:00
self.height = round(uniform(8.0, 12.0), 2)
self._add_height_entry()
last_height_entry_time = self.time
self.head_circumference = round(uniform(8.0, 12.0), 2)
self._add_head_circumference_entry()
last_head_circumference_entry_time = self.time
self.bmi = round(uniform(8.0, 12.0), 2)
self._add_bmi_entry()
last_bmi_entry_time = self.time
self._add_note_entry()
2022-04-04 01:13:25 +00:00
last_note_entry_time = self.time
while self.time < self.time_now:
self._add_sleep_entry()
if choice([True, False]):
self._add_diaperchange_entry()
self._add_feeding_entry()
self._add_diaperchange_entry()
2022-03-04 15:39:13 +00:00
self._add_pumping_entry()
if choice([True, False]):
self._add_tummytime_entry()
if choice([True, False]):
self._add_diaperchange_entry()
self._add_tummytime_entry()
2019-05-17 04:33:26 +00:00
if choice([True, False]):
self._add_temperature_entry()
if choice([True, False]):
2022-03-04 15:39:13 +00:00
self._add_pumping_entry()
2022-04-04 01:13:25 +00:00
if (self.time - last_note_entry_time).days > 1 and choice([True, False]):
self._add_note_entry()
last_note_entry_time = self.time
if (self.time - last_weight_entry_time).days > 6:
self._add_weight_entry()
last_weight_entry_time = self.time
2021-12-30 03:32:55 +00:00
if (self.time - last_height_entry_time).days > 6:
self._add_height_entry()
last_height_entry_time = self.time
if (self.time - last_head_circumference_entry_time).days > 6:
self._add_head_circumference_entry()
last_head_circumference_entry_time = self.time
if (self.time - last_bmi_entry_time).days > 6:
self._add_bmi_entry()
last_bmi_entry_time = self.time
@transaction.atomic
2022-03-04 15:39:13 +00:00
def _add_pumping_entry(self):
"""
2022-03-04 15:39:13 +00:00
Add a Pumping entry. This assumes a weekly interval.
:returns:
"""
self.amount = round(uniform(95.0, 102.0), 2)
notes = ""
if choice([True, False, False, False]):
notes = " ".join(self.faker.sentences(randint(1, 5)))
start = self.time + timedelta(minutes=randint(1, 60))
end = start + timedelta(minutes=randint(5, 20))
if end < self.time_now:
models.Pumping.objects.create(
child=self.child, amount=self.amount, start=start, end=end, notes=notes
).save()
@transaction.atomic
def _add_diaperchange_entry(self):
"""
Add a Diaper Change entry and advance self.time.
:returns:
"""
solid = choice([True, False, False, False])
wet = choice([True, False])
2022-02-10 00:00:30 +00:00
color = ""
if solid:
2022-02-10 00:00:30 +00:00
color = choice(models.DiaperChange._meta.get_field("color").choices)[0]
amount = Decimal("%d.%d" % (randint(0, 6), randint(1, 9)))
time = self.time + timedelta(minutes=randint(1, 60))
2022-02-10 00:00:30 +00:00
notes = ""
2020-02-16 22:59:40 +00:00
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2020-02-16 22:59:40 +00:00
if time < self.time_now:
2022-04-04 01:13:25 +00:00
instance = models.DiaperChange.objects.create(
child=self.child,
time=time,
wet=wet,
solid=solid,
color=color,
2020-02-16 22:59:40 +00:00
amount=amount,
2022-02-10 00:00:30 +00:00
notes=notes,
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
self.time = time
@transaction.atomic
def _add_feeding_entry(self):
"""
Add a Feeding entry and advance self.time.
:returns:
"""
2022-02-10 00:00:30 +00:00
method = choice(models.Feeding._meta.get_field("method").choices)[0]
amount = None
2022-02-10 00:00:30 +00:00
if method == "bottle":
amount = Decimal("%d.%d" % (randint(0, 6), randint(0, 9)))
start = self.time + timedelta(minutes=randint(1, 60))
end = start + timedelta(minutes=randint(5, 20))
2022-02-10 00:00:30 +00:00
notes = ""
2020-02-16 22:59:40 +00:00
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2020-02-16 22:59:40 +00:00
if end < self.time_now:
2022-04-04 01:13:25 +00:00
instance = models.Feeding.objects.create(
child=self.child,
start=start,
end=end,
2022-02-10 00:00:30 +00:00
type=choice(models.Feeding._meta.get_field("type").choices)[0],
method=method,
2020-02-16 22:59:40 +00:00
amount=amount,
2022-02-10 00:00:30 +00:00
notes=notes,
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
self.time = end
@transaction.atomic
def _add_note_entry(self):
"""
Add a Note entry.
:returns:
"""
note = self.faker.sentence()
2022-04-04 01:13:25 +00:00
instance = models.Note.objects.create(child=self.child, note=note)
instance.save()
self._add_tags(instance)
@transaction.atomic
def _add_sleep_entry(self):
"""
Add a Sleep entry and advance self.time. Between the hours of 18 and 6,
extend the minimum and maximum sleep duration settings.
:returns:
"""
if self.time.hour < 6 or self.time.hour > 18:
minutes = randint(60 * 2, 60 * 6)
else:
minutes = randint(30, 60 * 2)
end = self.time + timedelta(minutes=minutes)
2022-02-10 00:00:30 +00:00
notes = ""
2020-02-16 22:59:40 +00:00
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2020-02-16 22:59:40 +00:00
if end < self.time_now:
2022-04-04 01:13:25 +00:00
instance = models.Sleep.objects.create(
2022-02-10 00:00:30 +00:00
child=self.child, start=self.time, end=end, notes=notes
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
self.time = end
2019-05-17 04:33:26 +00:00
@transaction.atomic
def _add_temperature_entry(self):
"""
Add a Temperature entry. This assumes a weekly interval.
:returns:
"""
self.temperature = round(uniform(95.0, 102.0), 2)
2020-02-16 22:59:40 +00:00
2022-02-10 00:00:30 +00:00
notes = ""
2020-02-16 22:59:40 +00:00
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2020-02-16 22:59:40 +00:00
2022-04-04 01:13:25 +00:00
instance = models.Temperature.objects.create(
2022-02-10 00:00:30 +00:00
child=self.child, temperature=self.temperature, time=self.time, notes=notes
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
2019-05-17 04:33:26 +00:00
@transaction.atomic
def _add_tummytime_entry(self):
"""
Add a Tummy time entry and advance self.time.
:returns:
"""
2022-02-10 00:00:30 +00:00
milestone = ""
if choice([True, False]):
milestone = self.faker.sentence()
start = self.time + timedelta(minutes=randint(1, 60))
end = start + timedelta(minutes=randint(0, 10), seconds=randint(0, 59))
if (end - start).seconds < 20:
end = start + timedelta(minutes=1, seconds=30)
if end < self.time_now:
2022-04-04 01:13:25 +00:00
instance = models.TummyTime.objects.create(
2022-02-10 00:00:30 +00:00
child=self.child, start=start, end=end, milestone=milestone
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
self.time = end
@transaction.atomic
def _add_weight_entry(self):
"""
Add a Weight entry. This assumes a weekly interval.
:returns:
"""
self.weight += uniform(0.1, 0.3)
2020-02-16 22:59:40 +00:00
2022-02-10 00:00:30 +00:00
notes = ""
2020-02-16 22:59:40 +00:00
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2020-02-16 22:59:40 +00:00
2022-04-04 01:13:25 +00:00
instance = models.Weight.objects.create(
child=self.child,
2019-05-17 04:33:26 +00:00
weight=round(self.weight, 2),
2020-02-16 22:59:40 +00:00
date=self.time.date(),
2022-02-10 00:00:30 +00:00
notes=notes,
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
@transaction.atomic
def _add_height_entry(self):
"""
Add a height entry. This assumes a weekly interval.
:returns:
"""
self.height += uniform(0.1, 0.3)
2022-02-10 00:00:30 +00:00
notes = ""
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2022-04-04 01:13:25 +00:00
instance = models.Height.objects.create(
child=self.child,
height=round(self.height, 2),
date=self.time.date(),
2022-02-10 00:00:30 +00:00
notes=notes,
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
2021-12-30 03:32:55 +00:00
@transaction.atomic
def _add_head_circumference_entry(self):
"""
Add a head circumference entry. This assumes a weekly interval.
:returns:
"""
self.head_circumference += uniform(0.1, 0.3)
2022-02-10 00:00:30 +00:00
notes = ""
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2022-04-04 01:13:25 +00:00
instance = models.HeadCircumference.objects.create(
child=self.child,
head_circumference=round(self.head_circumference, 2),
date=self.time.date(),
2022-02-10 00:00:30 +00:00
notes=notes,
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
@transaction.atomic
def _add_bmi_entry(self):
"""
Add a BMI entry. This assumes a weekly interval.
:returns:
"""
self.bmi += uniform(0.1, 0.3)
2022-02-10 00:00:30 +00:00
notes = ""
if choice([True, False, False, False]):
2022-02-10 00:00:30 +00:00
notes = " ".join(self.faker.sentences(randint(1, 5)))
2022-04-04 01:13:25 +00:00
instance = models.BMI.objects.create(
2022-02-10 00:00:30 +00:00
child=self.child, bmi=round(self.bmi, 2), date=self.time.date(), notes=notes
2022-04-04 01:13:25 +00:00
)
instance.save()
self._add_tags(instance)
@transaction.atomic
def _add_tags(self, instance):
if choice([True, False, False, False]):
instance.tags.add(*choices(self.tags, k=randint(1, 5)))