def test_disordered_test(self):
     garden = Garden("VCRRGVRG\nRVGCCGCV",
                     students="Samantha Patricia Xander Roger".split())
     self.assertEqual("Violets Clover Radishes Violets".split(),
                      garden.plants("Patricia"))
     self.assertEqual("Radishes Grass Clover Violets".split(),
                      garden.plants("Xander"))
 def test_disordered_test(self):
     garden = Garden("VCRRGVRG\nRVGCCGCV",
                     students="Samantha Patricia Xander Roger".split())
     self.assertEqual("Violets Clover Radishes Violets".split(),
                      garden.plants("Patricia"))
     self.assertEqual("Radishes Grass Clover Violets".split(),
                      garden.plants("Xander"))
def test_load_config_from_json():

    garden = Garden(0,0,world)
    config = {'garden':{'capacity':5}, 'robot':{'speed':5}}
    with open('test_config.json', 'w+') as f:
        f.write(json.dumps(config))
    garden._load_config_from_json('test_config.json')
    assert garden.capacity == 5
Beispiel #4
0
def generate_garden_layout(library, north, west, plant_prefs):
    """
    Generate a list of boxes, containing a list of squares with plant names
    """

    garden = Garden(library, north, west)
    garden.generate(plant_prefs)

    return garden
def test_harvest():
    garden = Garden(0,0,world)
    garden.capacity = 5

    for i in range(5):
        assert garden.harvest()

    assert not garden.harvest()
    assert garden.is_fully_harvested()
Beispiel #6
0
 def __init__(self):
     self.garden = Garden()
     self.records = Records(sensors=self.garden.sensors)
     self.scheduler = BackgroundScheduler({
         'apscheduler.executors.default': {
             'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
             'max_workers': '1'
         }
     })
 def xtest_full_garden(self):
     garden = Garden("VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV")
     self.assertEqual("Violets Radishes Violets Radishes".split(),
                      garden.plants("Alice"))
     self.assertEqual("Clover Grass Clover Clover".split(),
                      garden.plants("Bob"))
     self.assertEqual("Grass Clover Clover Grass".split(),
                      garden.plants("Kincaid"))
     self.assertEqual("Grass Violets Clover Violets".split(),
                      garden.plants("Larry"))
Beispiel #8
0
def main():
    garden = Garden()
    flower1 = Flowers("yellow")
    flower2 = Flowers("blue")
    tree1 = Trees("purple")
    tree2 = Trees("orange")

    garden.add(flower1)
    garden.add(flower2)
    garden.add(tree1)
    garden.add(tree2)

    garden.describe_garden()
    garden.watering(40)
    garden.watering(70)
Beispiel #9
0
    def __init__(self):
        pygame.init()

        global env
        env = Garden(garden_size, tako_number)
        global task
        task = GardenTask(env)
        global experiment
        experiment = Continuous_MA_Experiment_Tako(task, env.tako_list)

        self.width = (garden_size * 50) + 400
        if garden_size < 8:
            self.height = 400
        else:
            self.height = (garden_size * 50)
        self.screen = pygame.display.set_mode((self.width, self.height))
        pygame.display.set_caption('Garden')
        self.clock = pygame.time.Clock()

        self.neur_background = pygame.Surface(self.screen.get_size())
        self.neur_background.fill((200, 255, 200))

        self.selected_Tako = None
        self.neur = None
        self.selected_Neuron = None
Beispiel #10
0
def load_gardens():
    """
    Load the dictionary of gardens if it already exists.
    Otherwise, create it and add the default garden.
    """
    try:
        with open("gardens.pickle", "rb") as file:
            gardens = pickle.load(file)
    except FileNotFoundError:
        gardens = {}
        default_garden = Garden("", "", 0, datetime.today().strftime("%d/%m/%Y"), " ")
        gardens[""] = default_garden

    return gardens
 def test_full_garden(self):
     garden = Garden("VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV")
     self.assertEqual("Violets Radishes Violets Radishes".split(),
                      garden.plants("Alice"))
     self.assertEqual("Clover Grass Clover Clover".split(),
                      garden.plants("Bob"))
     self.assertEqual("Grass Clover Clover Grass".split(),
                      garden.plants("Kincaid"))
     self.assertEqual("Grass Violets Clover Violets".split(),
                      garden.plants("Larry"))
 def test_bob_and_charlies_gardens(self):
     garden = Garden("VVCCGG\nVVCCGG")
     self.assertEqual(["Clover"] * 4, garden.plants("Bob"))
     self.assertEqual(["Grass"] * 4, garden.plants("Charlie"))
Beispiel #13
0
from tomate import Tomate
from potato import Potato
from concombre import Pickle
from garden import Garden

g = Garden()
g.add(Tomate())
p = Pickle()
p.grow(8)
g.add(p)
print(g.seed)
Beispiel #14
0
from garden import Garden
from datetime import date, datetime, timedelta
import slack

garden = Garden()

garden.send_no_show_message()
def test_load_config():
    garden = Garden(0,0,world)
    config = {'garden':{'capacity':5}, 'robot':{'speed':5}}

    garden._load_config(config)
    assert garden.capacity == 5
Beispiel #16
0
from garden import Garden
from datetime import date, datetime, timedelta

garden = Garden()

today = datetime.today()
yesterday = today - timedelta(days=1)
tomorrow = today + timedelta(days=1)

oldest = yesterday.timestamp()
latest = tomorrow.timestamp()

garden.collect_slack_messages(oldest, latest)
Beispiel #17
0
def createWorld():

    bedtime = events.SleepEvent(
        gT
    )  #   Initializing this here, not in events.py, because we need to refer to gT

    #gT.changeSeason()  #  Testing GameTime stuff here
    # for i in range(44):
    #   gT.advanceDate()

    #House Rooms:
    br = Room("Your Bedroom")
    lr = Room("Your Living Room")
    #bY = Room("Your Backyard. It contains a modest g is 6x2 feet large. ")
    bY = Room("Your Backyard")
    g = Garden(6, 2)
    g.putInRoom(bY)
    defaultBackyardGardenEvent = events.GardenEvent(g)
    bY.addRoomEvent("garden", defaultBackyardGardenEvent)
    #bY.roomEventTitles = ["garden"]
    #bY.roomEvents = [defaultBackyardGardenEvent]

    bed = Room("In Your Bed")
    bed.roomEventTitles = ["sleep"]
    bed.roomEvents = [bedtime]

    #External Rooms:
    outside = Room(
        "Outside"
    )  #   Generic 'outside' location, to tie together all of the colony's accessible locations

    farmersMarket = Room("The farmer's market")
    farmersMarketEvent = events.MarketEvent()
    # farmersMarket.roomEventTitles = ["market"]
    farmersMarket.addRoomEvent("market", farmersMarketEvent)
    #farmersMarket.roomEvents = [farmersMarketEvent]
    farmersMarketEvent.marketName = "the farmer's market"
    farmersMarketEvent.daysAvailable = ["sunday", "saturday"]

    gardenSupply = Room("'Gardener's Delight' Garden Supply Emporium")
    gardenSupply.roomEventTitles = [
        "vendor"
    ]  #   We can buy stuff in the garden supply
    gardenSupply.roomEvents = [events.gardenSupplyVendor]
    gardenSupply.roomEvents[0].vendorItemCategories = [
        "crop", "flower"
    ]  #  The garden supply store only sells crops and flowers.

    fieldOffice = Room("Wasteland Field Office")
    fO = FieldOffice("the field office")
    fO.putInRoom(fieldOffice)
    defaultFieldOfficeEvent = events.FieldOfficeEvent(fO)
    fieldOffice.addRoomEvent("field office", defaultFieldOfficeEvent)

    petStore = Room("Pet Store")
    petStore.roomEventTitles = ["vendor"]
    petStore.roomEvents = [events.petStoreVendor]

    Room.connectRooms(br, "living room", lr, "bedroom")
    Room.connectRooms(
        br, "to bed", bed,
        "out of bed")  #   Bed is a "room" that advances the day when you sleep
    Room.connectRooms(lr, "backyard", bY, "living room")
    Room.connectRooms(lr, "outside", outside, "inside")

    Room.connectRooms(outside, "farmers market", farmersMarket, "home")
    Room.connectRooms(outside, "garden supply", gardenSupply, "home")
    Room.connectRooms(outside, "field office", fieldOffice, "home")
    Room.connectRooms(outside, "pet store", petStore, "home")

    #   The items being created below are mostly just things for testing, and so I've commented them out for now. Sorry for how messy this section is.

    #i = Item("Macbook", "This is your 3019 16-Inch Macbook Oh.")

    #h = HealingItem("Juicebox", "(healing item) a bit of juice always helps")
    #h.healthRestore = 100
    #h.putInRoom(lr)
    #tS = Seed("test seed", "Seeds that grow into a beautiful hydrangea plant", 1, 1, 5, 25, 2)    #    test Seed
    # tS = Seed("Panicled Hydrangea Seed", "Seeds that grow into a beautiful hydrangea plant", 1, 15, 5, 25, 2, False, "crop")
    # tS.putInRoom(br),tS.putInRoom(br),tS.putInRoom(br)
    # tF = DirtPlotEffector("Fertilizer", "Makes the amount of time required for a seed to grow 2/3rds of its original duration!", 10)   #   test Fertilizer  #  Fertilizer is not implemented
    # tCP = CompletedPlant("Test", "test description", 25, 3, "test")  #   test CompletedPlant
    # potato = CompletedPlant("Potato", "A beautiful delicious potato", 5, 0, "crop")  #   testing potato
    #tCP.putInRoom(bY), potato.putInRoom(bY),potato.putInRoom(bY)
    # dS, dS2 = Seed("demo seed", "grows quick", 1, 1, 2.5, 7.5, 0,False,"crop"),Seed("demo seed", "grows quick", 1, 1, 2.5, 7.5, 0,False,"crop")
    #def __init__(self, name, desc, value, growthDuration, price, plantPrice, radiation, exotic, plantType):
    # dP = dS.becomePlant()
    # dP2 = dS2.becomePlant()
    # dP.fullyGrown, dP2.fullyGrown = True, True
    #
    #  dCP, dCP2 = dP.returnCompletedPlant(), dP2.returnCompletedPlant()
    #
    #  dCP.loc, dCP2.loc = br, br
    # tF.effect="fertilized"retu
    #tF.putInRoom(bY)
    # i = Item("Rock", "This is just a rock.")
    # i.putInRoom(br)
    player.location = br
    # dCP.putInRoom(br), dCP2.putInRoom(br)
    # player.pickup(dCP), player.pickup(dCP2)  #  Giving player completed demo plants
    # #i.putInRoom(br), i.putInRoom(br)
    # player.pickup(tS), player.pickup(tS), player.pickup(tS)
    # #player.pickup(tCP), player.pickup(potato),player.pickup(potato)
    # #player.location = fieldOffice
    # player.pickup(i)#, player.pickup(i)    #Pickup two macbooks
    #Monster("Bob the monster", 20, b)
    updater.dailyUpdateAll()

    player.location = br
Beispiel #18
0
    import garden.wiringpi_fake as wiringpi

from garden import Garden, RelayWiring, RelaySet


class SensorFake:
    def __init__(self, name):
        self.name = name
        self.value = None

    def read_value(self):
        self.value = 1
        return self.value


garden = Garden()


class TestGarden(unittest.TestCase):
    def setUp(self):
        if wiringpi.__doc__ and "Fake" in wiringpi.__doc__:
            wiringpi.pin_mode = [wiringpi.GPIO.INPUT] * 40
            wiringpi.pin_value = [0] * 40
            wiringpi.pin_mode_history = []
            wiringpi.pin_value_history = []

    def test_a_that_fogging_method_set_relays(self):
        # when
        garden.fogging()

        # than
Beispiel #19
0
from datetime import datetime

from garden import Garden
import pprint
import requests

from urllib.parse import urlparse

garden = Garden()

db = garden.get_database()

mongo_collection = db.get_collection("slack_messages")

def get_commit(commit_url):
    parse_result = urlparse(commit_url)
    # print(parse_result)
    (_, user, repo, commit, sha) = parse_result.path.split("/")

    api_url = 'https://api.github.com/repos/%s/%s/commits/%s' % (user, repo, sha)

    r = requests.get(api_url)

    # print(r.json())
    ts_datetime = datetime.strptime(r.json()["commit"]["author"]["date"], "%Y-%m-%dT%H:%M:%S%z")
    message = r.json()["commit"]["message"]
    ts = str(ts_datetime.timestamp())
    return {
        "user": user,
        "ts": ts,
        "ts_datetime": ts_datetime,
Beispiel #20
0
from garden import Garden

garden = Garden()

garden.trees.append({
    'especie': 'bananeira',
    'limite': 20,
    'fator': 1.11,
    'alturas': [4],
})
garden.trees.append({
    'especie': 'laranjeira',
    'limite': 15,
    'fator': 1.1,
    'alturas': [3]
})

garden.grow()
garden.show()
Beispiel #21
0
from plants import Flower, Tree
from garden import Garden

garden = Garden()

garden.add(Flower("yellow"))
garden.add(Flower("blue"))
garden.add(Tree("purple"))
garden.add(Tree("orange"))

garden.garden_status()

garden.water_plants(40)

garden.garden_status()

garden.water_plants(70)

garden.garden_status()
 def xtest_bob_and_charlies_gardens(self):
     garden = Garden("VVCCGG\nVVCCGG")
     self.assertEqual(["Clover"] * 4, garden.plants("Bob"))
     self.assertEqual(["Grass"] * 4, garden.plants("Charlie"))
 def test_alices_garden(self):
     self.assertEqual("Radishes Clover Grass Grass".split(),
                      Garden("RC\nGG").plants("Alice"))
Beispiel #24
0
class Gardener:
    """
    Gardener manages garden according schedule and collected sensor data.
     * Garden - Controls HW I/O - simple stateless servant for single thread use.
       * sensors: temperature (TODO: water level, light density, ...)
       * relays: pump, fan, fogger
     * Records - Via scheduler collects and store sensors data + current garden state.

     * Web server shows
       * current garden state (TODO)
       * light version of sensor data history
       * next planned maintenance action (TODO)
       * buttons for manipulation with garden
    """
    def __init__(self):
        self.garden = Garden()
        self.records = Records(sensors=self.garden.sensors)
        self.scheduler = BackgroundScheduler({
            'apscheduler.executors.default': {
                'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
                'max_workers': '1'
            }
        })

    def reschedule_job(self, job_id):
        period_minutes = self.compute_period(
            job_id, self.garden.city_temperature.value)
        last_job_run = self.garden.get_last_job_run(job_id)
        next_job_run = max((self.get_asap_schedule(),
                            last_job_run + timedelta(minutes=period_minutes)))
        self.scheduler.reschedule_job(job_id,
                                      trigger='cron',
                                      minute="*/{}".format(period_minutes),
                                      start_date=str(next_job_run))

    def sensors_refresh(self):
        old_temperature = self.garden.city_temperature.value
        self.garden.sensors_refresh()
        new_temperature = self.garden.city_temperature.value

        if old_temperature != new_temperature and new_temperature:
            self.reschedule_job('FOGGING')
            self.reschedule_job('WATERING')

    def send_sms_report(self):
        message = 'I am alive.'
        for sensor in self.garden.sensors:
            message += " {}:{}".format(sensor.name, str(sensor.value))
        message += " f:{}/{} w:{}/{}".format(
            self.get_job_period("FOGGING"),
            self.garden.get_job_run_count("FOGGING"),
            self.get_job_period("WATERING"),
            self.garden.get_job_run_count("WATERING"))
        utils.sms.send_sms(message)

    def working_loop(self):
        # shared cross threads
        threading.gardener = self

        # default schedule
        cron_params = {
            'trigger': 'cron',
            'misfire_grace_time': MISFIRE_GRACE_TIME
        }
        self.scheduler.add_job(self.garden.watering, trigger='date')
        self.scheduler.add_job(self.garden.watering,
                               minute='*/20',
                               id='WATERING',
                               **cron_params)
        self.scheduler.add_job(self.garden.fogging,
                               minute='*/3',
                               id='FOGGING',
                               **cron_params)

        # sensors maintenance
        self.scheduler.add_job(self.sensors_refresh,
                               minute='*/10',
                               **cron_params)
        self.scheduler.add_job(self.records.write_values,
                               minute='*/10',
                               kwargs={'file': config.SensorData.FULL_FILE},
                               **cron_params)
        self.scheduler.add_job(self.records.write_values,
                               hour='*',
                               kwargs={'file': config.SensorData.WEB_FILE},
                               **cron_params)
        self.scheduler.add_job(
            self.records.trim_records,
            week='*',  # show on web only latest 30 days
            kwargs={
                'file': config.SensorData.WEB_FILE,
                'count': 24 * 7 * 4
            },
            **cron_params)
        self.scheduler.add_job(self.send_sms_report, hour='12', **cron_params)

        # TODO: create more oxygen when high temperature via extra long pumping cycle?

        # network maintenance
        self.scheduler.add_job(utils.network.check_and_fix,
                               hour='*',
                               kwargs={
                                   'address': config.RouterAddress,
                                   'network': 'wlan0'
                               },
                               **cron_params)
        self.scheduler.add_job(utils.system.reboot, hour='0', **cron_params)

        logging.info('Starting scheduler.')
        self.scheduler.start()

        # web server needs main thread for its signal handling
        logging.info('Starting web server.')
        web_server.run(**config.WebServer)

        self.scheduler.shutdown()

    def get_job_period(self, job_id):
        trigger = self.scheduler.get_job(job_id).trigger
        period = re.search(r"cron\[minute='\*/(\d+)'\]", str(trigger))
        return int(period.group(1)) if period else 0

    def get_job_next_run_time(self, job_id):
        return self.scheduler.get_job(job_id).next_run_time

    def start_job(self, job_id):
        # FIXME
        job = self.scheduler.get_job(job_id)

    @staticmethod
    def get_asap_schedule():
        return datetime.now() + timedelta(seconds=2)

    @staticmethod
    def compute_period(job_id, temperature):

        if job_id == 'FOGGING':
            return int(2 * 4 * 60 /
                       (temperature -
                        4)**1.5) if 4 < temperature < 27 else INFINITE_MINUTES
        elif job_id == 'WATERING':
            return int(4 * 24 * 60 /
                       (temperature -
                        4)**2) if 4 < temperature < 27 else INFINITE_MINUTES
        else:
            assert 0
Beispiel #25
0
def run_event_loop(logger, gardens, garden, window):
    """
    Display and interact with the main window and subwindows using an event loop.

    Create, select, display, update, and remove gardens 
    and the creatures, plants, and tasks they contain.
    Save the gardens dict as gardens.pickle.
    If a fatal exception occurs, log it in gardenlife.log.
    """

    # Keeps track of whether any changes have been made since the gardens dict was saved
    gardens_changed = False

    try:
        while True:
            event, values = window.read()
            # print(event, values)

            ##################### Menu & Window Closure Events #####################

            # See if user wants to quit or attempted to close the window
            if event in ("Exit", sg.WINDOW_CLOSE_ATTEMPTED_EVENT):

                if gardens_changed:
                    subwindows.unsaved_changes_window(window, gardens)
                else:
                    break

            elif event == "Save":
                with open("gardens.pickle", "wb") as file:
                    pickle.dump(gardens, file)
                gardens_changed = False

            elif event == "About...":
                popups.about()

            elif event == "Open web tutorial":
                webbrowser.open("https://github.com/jonboland/gardenlife/blob/master/README.rst")

            ################ Creature, Plant, & Task Summary Events ################

            elif event == "VIEW ALL CREATURES":
                subwindows.view_creatures_window(window, garden)

            elif event == "VIEW ALL PLANTS":
                subwindows.view_plants_window(window, garden)

            elif event == "VIEW EDIBLE PLANTS":
                subwindows.view_plants_window(window, garden, attr="edible", title="Edible ")

            elif event == "VIEW ALL TASKS":
                subwindows.view_tasks_window(window, garden)

            ######################### Manage Garden Events #########################

            elif event == "GARDEN CREATE/UPDATE":
                # Validate garden name and ownership info
                g_name = values["-GARDEN NAME-"].strip()
                g_owners = values["-OWNER NAMES-"].strip()
                g_since = values["-OWNED SINCE-"].strip()
                if not g_name:
                    popups.invalid_name("garden name")
                    continue
                if not g_owners:
                    popups.invalid_name("owner names")
                    continue
                try:
                    event_funcs.check_date_validity(g_since)
                except ValueError:
                    popups.invalid_date(field="owned since", date=g_since)
                # If there are no validation errors, create/update the garden
                else:
                    cu_garden = Garden(
                        g_name, values["-LOCATION-"], values["-SIZE-"], g_since, g_owners.split()
                    )
                    # If garden already exists add all existing items to the updated version
                    garden_instance = gardens.get(g_name)
                    if garden_instance:
                        cu_garden.creatures = garden_instance.creatures
                        cu_garden.plants = garden_instance.plants
                        cu_garden.tasks = garden_instance.tasks
                    # Add created/updated garden to gardens dict. Overwrite if already exists
                    gardens[g_name] = cu_garden
                    # Update dropdowns and clear field values and links
                    event_funcs.update_garden_dropdown(window, gardens)
                    event_funcs.clear_all_item_dropdowns(window)
                    event_funcs.clear_all_values_and_links(window, garden)
                    gardens_changed = True

            elif event == "GARDEN REMOVE":
                if not values["-SELECT GARDEN-"]:
                    continue
                g_confirmation = popups.remove_confirmation(garden.name, "garden")
                if g_confirmation == "OK":
                    del gardens[values["-GARDEN NAME-"]]
                    event_funcs.update_garden_dropdown(window, gardens)
                    event_funcs.clear_all_item_dropdowns(window)
                    event_funcs.clear_all_values_and_links(window, garden)
                    gardens_changed = True

            elif event == "-SELECT GARDEN-":  # A garden is selected from the dropdown
                # Load the selected garden
                garden = gardens[values["-SELECT GARDEN-"]]
                # If the default garden (blank row) is selected, clear fields
                if not values["-SELECT GARDEN-"]:
                    event_funcs.clear_garden_values(window)
                    event_funcs.clear_summary_values(window)
                # Otherwise, update the fields with the selected garden's values
                else:
                    window["-GARDEN NAME-"].update(garden.name)
                    window["-LOCATION-"].update(garden.location)
                    window["-SIZE-"].update(garden.size)
                    window["-OWNER NAMES-"].update(" ".join(garden.owners))
                    window["-OWNED SINCE-"].update(garden.since)
                    # And update the associated summary fields
                    window["-SUMMARY GARDEN NAME-"].update(garden.name)
                    window["-SUMMARY LOCATION-"].update(garden.location)
                    window["-SUMMARY SIZE-"].update(garden.garden_size())
                    window["-SUMMARY OWNED BY-"].update(garden.ownership())
                    window["-SUMMARY OWNED FOR-"].update(garden.ownership_length())
                    window["-SUMMARY TOTAL CREATURES-"].update(len(garden.creatures))
                    window["-SUMMARY TOTAL PLANTS-"].update(len(garden.plants))
                    event_funcs.update_task_summaries(window, garden)
                # Then update the item dropdowns and clear item field values and links
                event_funcs.update_all_item_dropdowns(window, garden)
                event_funcs.clear_all_item_values_and_links(window, garden)

            ####################### Manage Creatures Events ########################

            elif event == "CREATURE CREATE/UPDATE":
                # Validate garden name, creature name and appeared date
                c_name = values["-CREATURE NAME-"].strip()
                c_appeared = values["-CREATURE APPEARED DATE-"].strip()
                # Check that a garden has been selected
                if not values["-SELECT GARDEN-"]:
                    popups.garden_not_selected("creature")
                    continue
                if not c_name:
                    popups.invalid_name("creature name")
                    continue
                try:
                    if c_appeared:
                        event_funcs.check_date_validity(c_appeared)
                except ValueError:
                    popups.invalid_date(field="appeared date", date=c_appeared)

                else:
                    creature = Creature(
                        name=c_name,
                        org_type=values["-CREATURE TYPE-"],
                        appeared=c_appeared,
                        notes=values["-CREATURE NOTES-"],
                        impact=values["-CREATURE IMPACT SLIDER-"],
                        prevalence=values["-CREATURE PREVALENCE SLIDER-"],
                        trend=values["-CREATURE TREND SLIDER-"],
                    )
                    if values["-CREATURE STATUS-"] == "Archived":
                        creature.status.archive()
                    garden.add_item("creatures", creature)
                    event_funcs.update_creature_dropdowns(window, garden)
                    event_funcs.clear_creature_values(window)
                    # Clear the task fields and organism links
                    event_funcs.clear_task_values(window)
                    event_funcs.clear_organism_links(window, garden)
                    # Update the associated summary field
                    window["-SUMMARY TOTAL CREATURES-"].update(len(garden.creatures))
                    gardens_changed = True

            elif event == "CREATURE REMOVE":
                if not values["-CREATURE NAME-"] in garden.creatures:
                    popups.item_not_created("creature")
                    continue
                c_confirmation = popups.remove_confirmation(values["-CREATURE NAME-"], "creature")
                if c_confirmation == "OK":
                    garden.remove_item("creatures", values["-CREATURE NAME-"])
                    event_funcs.update_creature_dropdowns(window, garden)
                    event_funcs.clear_creature_values(window)
                    event_funcs.clear_task_values(window)
                    event_funcs.clear_organism_links(window, garden)
                    window["-SUMMARY TOTAL CREATURES-"].update(len(garden.creatures))
                    gardens_changed = True

            elif event == "-CREATURE NAME-":
                if not values["-CREATURE NAME-"]:
                    event_funcs.clear_creature_values(window)
                    continue
                # If a creature is selected populate the relevant fields with its values
                creature_instance = garden.creatures.get(values["-CREATURE NAME-"])
                window["-CREATURE NAME-"].update(creature_instance.name)
                window["-CREATURE TYPE-"].update(creature_instance.org_type)
                window["-CREATURE APPEARED DATE-"].update(creature_instance.appeared)
                window["-CREATURE STATUS-"].update(creature_instance.status.get())
                window["-CREATURE NOTES-"].update(creature_instance.notes)
                window["-CREATURE IMPACT SLIDER-"].update(creature_instance.impact)
                window["-CREATURE PREVALENCE SLIDER-"].update(creature_instance.prevalence)
                window["-CREATURE TREND SLIDER-"].update(creature_instance.trend)

            ######################### Manage Plant Events ##########################

            elif event == "PLANT CREATE/UPDATE":
                # Validate plant name and planted date
                p_name = values["-PLANT NAME-"].strip()
                p_planted = values["-PLANT PLANTED DATE-"].strip()
                # Check that a garden has been selected
                if not values["-SELECT GARDEN-"]:
                    popups.garden_not_selected("plant")
                    continue
                if not p_name:
                    popups.invalid_name("plant name")
                    continue
                try:
                    if p_planted:
                        event_funcs.check_date_validity(p_planted)
                except ValueError:
                    popups.invalid_date(field="planted date", date=p_planted)

                else:
                    plant = Plant(
                        name=p_name,
                        org_type=values["-PLANT TYPE-"],
                        planted=p_planted,
                        edible=values["-PLANT EDIBLE-"],
                        notes=values["-PLANT NOTES-"],
                        impact=values["-PLANT IMPACT SLIDER-"],
                        prevalence=values["-PLANT PREVALENCE SLIDER-"],
                        trend=values["-PLANT TREND SLIDER-"],
                    )
                    if values["-PLANT STATUS-"] == "Archived":
                        plant.status.archive()
                    garden.add_item("plants", plant)
                    event_funcs.update_plant_dropdowns(window, garden)
                    event_funcs.clear_plant_values(window)
                    event_funcs.clear_task_values(window)
                    event_funcs.clear_organism_links(window, garden)
                    window["-SUMMARY TOTAL PLANTS-"].update(len(garden.plants))
                    gardens_changed = True

            elif event == "PLANT REMOVE":
                if not values["-PLANT NAME-"] in garden.plants:
                    popups.item_not_created("plant")
                    continue
                p_confirmation = popups.remove_confirmation(values["-PLANT NAME-"], "plant")
                if p_confirmation == "OK":
                    garden.remove_item("plants", values["-PLANT NAME-"])
                    event_funcs.update_plant_dropdowns(window, garden)
                    event_funcs.clear_plant_values(window)
                    event_funcs.clear_task_values(window)
                    event_funcs.clear_organism_links(window, garden)
                    window["-SUMMARY TOTAL PLANTS-"].update(len(garden.plants))
                    gardens_changed = True

            elif event == "-PLANT NAME-":
                if not values["-PLANT NAME-"]:
                    event_funcs.clear_plant_values(window)
                    continue
                # If a plant is selected populate the relevant fields with its values
                plant_instance = garden.plants.get(values["-PLANT NAME-"])
                window["-PLANT NAME-"].update(plant_instance.name)
                window["-PLANT TYPE-"].update(plant_instance.org_type)
                window["-PLANT PLANTED DATE-"].update(plant_instance.planted)
                window["-PLANT STATUS-"].update(plant_instance.status.get())
                window["-PLANT EDIBLE-"].update(plant_instance.edible)
                window["-PLANT NOTES-"].update(plant_instance.notes)
                window["-PLANT IMPACT SLIDER-"].update(plant_instance.impact)
                window["-PLANT PREVALENCE SLIDER-"].update(plant_instance.prevalence)
                window["-PLANT TREND SLIDER-"].update(plant_instance.trend)

            ########################## Manage Task Events ##########################

            elif event == "TASK CREATE/UPDATE":
                # Check that a garden has been selected
                if not values["-SELECT GARDEN-"]:
                    popups.garden_not_selected("task")
                    continue
                # Strip and validate task name and set schedule values
                # NB: Frequency is not validated because it's a readonly dropdown
                t_name = values["-TASK NAME-"].strip()
                start_date = values["-TASK START-"].strip()
                count = values["-TASK COUNT-"].strip()
                bymonth = values["-TASK BY MONTH-"].strip()
                interval = values["-TASK INTERVAL-"].strip()
                if not t_name:
                    popups.invalid_name("task name")
                    continue
                try:
                    if start_date:
                        event_funcs.check_date_validity(start_date)
                except ValueError:
                    popups.invalid_date(field="first due", date=start_date)
                    continue
                if count and not count.isdigit():
                    popups.invalid_digit(field="count", digit=count)
                elif bymonth and any(month not in MONTHS for month in bymonth.split(" ")):
                    popups.invalid_bymonth(bymonth)
                elif interval and not interval.isdigit():
                    popups.invalid_digit(field="interval", digit=interval)
                # If there are no validation errors, create/update the task
                else:
                    task = Task(
                        name=t_name,
                        assignee=values["-TASK ASSIGNEE-"],
                        length=values["-TASK LENGTH-"],
                        linked_creatures=values["-TASK LINKED CREATURES-"],
                        linked_plants=values["-TASK LINKED PLANTS-"],
                        description=values["-TASK NOTES-"],
                    )

                    task.set_schedule(
                        start_date=start_date,
                        freq=values["-TASK FREQUENCY-"],
                        count=count,
                        bymonth=bymonth,
                        interval=interval,
                    )
                    # Handle rare situation where provided shedule doesn't produce any due dates
                    if not task.schedule:
                        popups.no_due_dates()
                        continue

                    if values["-TASK STATUS-"] == "Archived":
                        task.status.archive()
                    # If the task already exists add any pre-existing completed dates to it
                    task_instance = garden.tasks.get(values["-TASK NAME-"])
                    if task_instance:
                        task.completed_dates = task_instance.completed_dates
                    # Add the task to the garden, overwriting the old version if it already exists
                    garden.add_item("tasks", task)
                    event_funcs.update_task_dropdown(window, garden)
                    # Clear the task fields and variable once the task has been added to the garden
                    event_funcs.clear_task_values(window)
                    event_funcs.clear_organism_links(window, garden)
                    task = None
                    # Update the task numbers shown on the summary tab
                    event_funcs.update_task_summaries(window, garden)
                    gardens_changed = True

            elif event == "TASK REMOVE":
                if not values["-TASK NAME-"] in garden.tasks:
                    popups.item_not_created("task")
                    continue
                t_confirmation = popups.remove_confirmation(values["-TASK NAME-"], "task")
                if t_confirmation == "OK":
                    garden.remove_item("tasks", values["-TASK NAME-"])
                    event_funcs.update_task_dropdown(window, garden)
                    event_funcs.clear_task_values(window)
                    task = None
                    event_funcs.clear_organism_links(window, garden)
                    event_funcs.update_task_summaries(window, garden)
                    gardens_changed = True

            elif event == "ADD PROGRESS":
                # Check the task variable exists and has been assigned to a task
                if "task" in locals() and task:
                    # Open the progress subwindow and set gardens_changed flag if progress added
                    if subwindows.add_progress_window(window, task):
                        gardens_changed = True
                else:
                    popups.item_not_created("task", "progress can be added")

            elif event == "-TASK NAME-":
                if not values["-TASK NAME-"]:
                    event_funcs.clear_task_values(window)
                    event_funcs.clear_organism_links(window, garden)
                    task = None
                    continue
                # If a task is selected populate the relevant fields with its values
                task_instance = garden.tasks[values["-TASK NAME-"]]
                window["-TASK PROGRESS-"].update(task_instance.get_current_progress())
                window["-TASK NEXT DUE-"].update(task_instance.get_next_due_date())
                window["-TASK ASSIGNEE-"].update(task_instance.assignee)
                window["-TASK LENGTH-"].update(task_instance.length)
                window["-TASK LINKED CREATURES-"].set_value(task_instance.linked_creatures)
                window["-TASK LINKED PLANTS-"].set_value(task_instance.linked_plants)
                window["-TASK STATUS-"].update(task_instance.status.get())
                window["-TASK NOTES-"].update(task_instance.description)
                window["-TASK START-"].update(task_instance.raw_schedule["start date"])
                window["-TASK FREQUENCY-"].update(task_instance.raw_schedule["freq"])
                window["-TASK COUNT-"].update(task_instance.raw_schedule["count"])
                window["-TASK BY MONTH-"].update(task_instance.raw_schedule["bymonth"])
                window["-TASK INTERVAL-"].update(task_instance.raw_schedule["interval"])
                # Then assign instance to task variable so progress can be added
                task = task_instance

    # Handle fatal exceptions gracefully and log them in the gardenlife.log file
    except Exception as ex:
        logger.exception("Fatal Error")
        popups.fatal_error(ex)

    # Finish up by removing from the screen
    window.close()
Beispiel #26
0
import random
import sys
import os
from plant import Plants
from garden import Garden
from flower import Flower
from tree import Tree

myGarden = Garden()

yellowFlower = Flower('yellow')
blueFlower = Flower('blue')
purpleTree = Tree('purple')
orangeTree = Tree('orange')

myGarden.addToGarden(yellowFlower)
myGarden.addToGarden(blueFlower)
myGarden.addToGarden(purpleTree)
myGarden.addToGarden(orangeTree)

print('\n')
myGarden.printGarden()
print('\n')
myGarden.watering(20)
myGarden.printGarden()
print('\n')
myGarden.watering(30)
myGarden.printGarden()
print('\n')
myGarden.watering(40)
myGarden.printGarden()