def runWorld():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("Bottle-Filling Factory - World View - VirtuaPlant")
    clock = pygame.time.Clock()
    running = True

    space = pymunk.Space()
    space.gravity = (0.0, -900.0)

    # Limit switch with bottle bottom
    space.add_collision_handler(0x1, 0x2, begin=bottle_in_place)
    # Level sensor with water
    space.add_collision_handler(0x4, 0x5, begin=level_ok)
    # Level sensor with ground
    space.add_collision_handler(0x4, 0x6, begin=no_collision)
    # Limit switch with ground
    space.add_collision_handler(0x1, 0x6, begin=no_collision)
    # Limit switch with bottle side
    space.add_collision_handler(0x1, 0x3, begin=no_collision)
    # Level sensor with bottle side
    space.add_collision_handler(0x4, 0x3, begin=no_collision)
    # Bottle in with bottle sides and bottom
    space.add_collision_handler(0x7, 0x2, begin=no_collision, separate=add_new_bottle)
    space.add_collision_handler(0x7, 0x3, begin=no_collision)

    base = add_base(space)
    nozzle = add_nozzle(space)
    limit_switch = add_limit_switch(space)
    level_sensor = add_level_sensor(space)
    bottle_in = add_bottle_in_sensor(space)
    
    global bottles
    bottles.append(add_bottle(space))

    balls = []

    ticks_to_next_ball = 1

    fontBig = pygame.font.SysFont(None, 40)
    fontMedium = pygame.font.SysFont(None, 26)
    fontSmall = pygame.font.SysFont(None, 18)

    while running:
        clock.tick(FPS)

        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                running = False

        screen.fill(THECOLORS["white"])
        
        if PLCGetTag(PLC_TAG_RUN):

                # Motor Logic
                if (PLCGetTag(PLC_TAG_LIMIT_SWITCH) == 1):
                    PLCSetTag(PLC_TAG_MOTOR, 0)
                
                if (PLCGetTag(PLC_TAG_LEVEL_SENSOR) == 1):
                    PLCSetTag(PLC_TAG_MOTOR, 1)
                    
                ticks_to_next_ball -= 1
                
                if not PLCGetTag(PLC_TAG_LIMIT_SWITCH):
                    PLCSetTag(PLC_TAG_MOTOR, 1)

                if ticks_to_next_ball <= 0 and PLCGetTag(PLC_TAG_NOZZLE):
                    ticks_to_next_ball = 1
                    ball_shape = add_ball(space)
                    balls.append(ball_shape)

                # Move the bottles
                if PLCGetTag(PLC_TAG_MOTOR) == 1:
                    for bottle in bottles:
                        bottle[0].body.position.x += 0.25
        else:
            PLCSetTag(PLC_TAG_MOTOR, 0)

        # Draw water balls
        # Remove off-screen balls
        balls_to_remove = []
        for ball in balls:
            if ball.body.position.y < 150 or ball.body.position.x > SCREEN_WIDTH+150:
                balls_to_remove.append(ball)

            draw_ball(screen, ball)

        for ball in balls_to_remove:
            space.remove(ball, ball.body)
            balls.remove(ball)

        # Draw bottles
        for bottle in bottles:
            if bottle[0].body.position.x > SCREEN_WIDTH+150 or bottle[0].body.position.y < 150:
                space.remove(bottle, bottle[0].body)
                bottles.remove(bottle)
                continue
            draw_lines(screen, bottle)

        # Draw the base and nozzle
        draw_polygon(screen, base)
        draw_polygon(screen, nozzle)
        # Draw the limit switch
        draw_ball(screen, limit_switch, THECOLORS['green'])
        # Draw the level sensor
        draw_ball(screen, level_sensor, THECOLORS['red'])

        title = fontMedium.render(str("Bottle-filling factory"), 1, THECOLORS['deepskyblue'])
        name = fontBig.render(str("VirtuaPlant"), 1, THECOLORS['gray20'])
        instructions = fontSmall.render(str("(press ESC to quit)"), 1, THECOLORS['gray'])
        screen.blit(title, (10, 40))
        screen.blit(name, (10, 10))
        screen.blit(instructions, (SCREEN_WIDTH-115, 10))

        space.step(1/FPS)
        pygame.display.flip()

    # Stop reactor if running
    if reactor.running:
        reactor.callFromThread(reactor.stop)

#########################################
# Modbus Server Code
#########################################
dataset/ETHPy150Open jseidl/virtuaplant/plants/bottle-filling/world.py/runWorld/original