def update_friends(request, caller_context, container_user):
    
    response = { 'success' : False,
                'message' : 'unknown error'}
    if request.method != "POST":
        response.message ='only POST method is supported'
    else:    
        friends_controller = Friends_controller()
        friends_json = request.raw_post_data
        logging.debug('friends json from update_friends: %s' % friends_json)
        decoder = simplejson.JSONDecoder()
        friends = decoder.decode(friends_json)
        try:
            pyramidController = PyramidController()
            saved, failed = friends_controller.save_container_friends(container_user, friends)
            friend_pyramid_ids = pyramidController.get_friend_pyramid_ids(container_user.character, True)
            response['success'] = True
            response['message'] = 'friend list updated - %d saved, %d failed to save' % (saved, failed) 
            response['friendPyramidCount'] = len(friend_pyramid_ids)
        except Exception, e:
            logging.warn('failed to save friends')
            logging.warn('friends json: %s' % friends_json)
            logging.exception(e)
            response['success'] = False
            response['message'] = 'error saving friends'
def expire_pyramids(request, caller_context, container_user):
    pyramidController = PyramidController()
    expired_count, warning_count = pyramidController.handle_expiring_pyramids(caller_context.config)
    if expired_count == 0 and warning_count == 0:
        return HttpResponse('nothing expired', 'text/html')
    else:
        return HttpResponse('expired %d pyramids, warned %d players about expiring pyramids' % (expired_count, warning_count), 'text/html')
def get_paged_pyramids(config, pyramid_ids, container_user, page_size=10, active_page=1, active_position=1):
    ''' move to controller
    '''
    pyramidController = PyramidController()
    paginator = Paginator(pyramid_ids, page_size) 
    pyramid_display = Pyramid_display()

    try:
        pyramid_page = paginator.page(active_page)
    except (EmptyPage, InvalidPage):
        pyramid_page = paginator.page(1)

    pyramid_display.active_pyramid_position = active_position
    pyramid_display.page_size = page_size
    index = 1
    pyramid_display.positions = []
    for position in range(pyramid_page.start_index(), pyramid_page.end_index() + 1):
        positions = Positions()
        positions.position_abs = position
        positions.position_rel = index
        pyramid_display.positions.append(positions)
        index += 1

    if len(pyramid_ids) > 0:
        pyramid_id = pyramid_ids[page_size * (active_page - 1) + active_position - 1]
        pyramid_display.pyramid = Pyramid.get_by_id(pyramid_id)
        if pyramid_display.pyramid == None:
            raise RuntimeError('supplied pyramid_id %d was not found in the data store' % (pyramid_id))
        pyramid_display.bricks = pyramidController.get_bricks_from_pyramid(pyramid_display.pyramid)
        pyramid_display.brick_ids = []
        expired, expire_text = pyramid_display.pyramid.get_expire_text(config.pyramid_lifetime_hours)
        if expired:
            pyramid_display.expire_time_text = 'Expired %s ago' % expire_text
        else:
            pyramid_display.expire_time_text = '%s left to split' % expire_text
#        brick_display_left_pos = (320, 
#                                  165, 439, 
#                                  127, 267, 398, 538, 
#                                  61, 142, 224, 305, 386, 469, 550, 631,)

        brick_display_left_pos = (320, 
                                  264, 378, 
                                  181, 278, 376, 473, 
                                  76, 154, 232, 310, 388, 466, 544, 622,)

        pyramid_display.viewer_brick_descriptions = [];
        for brick in pyramid_display.bricks:
            pyramid_display.brick_ids.append(brick.key().id())
            if brick.character and container_user and container_user.character == brick.character and brick.brick_description:
                pyramid_display.viewer_brick_descriptions.append(brick.brick_description)
            brick.left_pos = brick_display_left_pos[brick.position_in_pyramid - 1]
            
        encoder = simplejson.JSONEncoder()
        pyramid_display.viewer_brick_description_json = encoder.encode(pyramid_display.viewer_brick_descriptions)

    if container_user and container_user.character and container_user.character.key() in pyramid_display.pyramid.character_keys:
        pyramid_display.viewer_in_pyramid = True
    
    return pyramid_display, paginator, pyramid_page
def main(request, caller_context, container_user, page=1):
    
    pyramidController = PyramidController()
    chamberController = ChamberController()
    characterController = CharacterController()
    
    current_time = datetime.utcnow() - timedelta(hours = 7) #show Pac time to see if this page gets cached

    if not container_user:
        #user isn't logged in, show some open pyramids
        pyramid_ids = pyramidController.find_open_pyramid_ids(None, 1000)
        if len(pyramid_ids) < 10: # if there are fewer than 10 open pyramids, create one 
            pyramid = pyramidController.create_new_pyramid(4, 3, 100) # 4 total levels, fill 3 levels, $100 price
            pyramid_ids.append(pyramid.key().id())
            logging.debug('created new pyramid: ' + pyramid.to_xml())
        if pyramid_ids:
            pyramid_display, paginator, pyramid_page = get_paged_pyramids(caller_context.config, pyramid_ids, container_user)
        group = 'open'
        return render_to_response('_main.html', locals())

    if caller_context.platform == 'myspace_iframe':
        logging.debug('getting friends from container')
        friends_controller = Friends_controller()
        viewer_friends = friends_controller.refresh_container_friends(container_user)
        encoder = simplejson.JSONEncoder()
        viewer_friends_json = encoder.encode(viewer_friends)

    pyramid_ids = None
    if container_user.character:
        status_bar_dict = characterController.get_status_bar_dict(caller_context.config, container_user.character)
        pyramid_ids = pyramidController.get_character_pyramid_ids(container_user.character, True)
        if pyramid_ids:
            pyramid_display, paginator, pyramid_page = get_paged_pyramids(caller_context.config, pyramid_ids, container_user)
            group = 'joined'
            return render_to_response('_main.html', locals())

    # do this here?  refresh friends?
    #saved, failed = friends_controller.save_container_friends(container_user, viewer_friends)
    #friend_pyramid_ids = pyramidController.get_friend_pyramid_ids(container_user.character, True)

    pyramid_ids = pyramidController.find_open_pyramid_ids(None, 200)
    if pyramid_ids:
        pyramid_display, paginator, pyramid_page = get_paged_pyramids(caller_context.config, pyramid_ids, container_user)
    group = 'open'
    return render_to_response('_main.html', locals())
def pyramids(request, caller_context, container_user, group, active_page=1, active_position=1):
    '''
    get page of pyramid by taking a pyramid id and finding its page
    '''
    pyramidController = PyramidController()
    pyramid_ids = None
    if (group == "joined"):
        pyramid_ids = pyramidController.get_character_pyramid_ids(container_user.character, True)
    elif (group == "friends"):
        pyramid_ids = pyramidController.get_friend_pyramid_ids(container_user.character, True)
    elif (group == "invited"):
        pyramid_ids, invites = pyramidController.get_invited_pyramid_ids(container_user, True)
    elif (group == "open"):
        character = None
        if container_user:
            character = container_user.character
        pyramid_ids = pyramidController.find_open_pyramid_ids(character, 1000)
        if len(pyramid_ids) < 10: # if there are fewer than 10 open pyramids, create one 
            pyramid = pyramidController.create_new_pyramid(4, 3, 100) # 4 total levels, fill 3 levels, $100 price
            pyramid_ids.append(pyramid.key().id())
            logging.debug('created new pyramid: ' + pyramid.to_xml())
        else:
            logging.debug('found open pyramids')
        #controller.set_game_invite(pyramid, container_user.character)
    elif (group == 'condemned'):
        pyramid_ids = pyramidController.get_character_pyramid_ids(container_user.character, active=False, paid=False)
        
    if pyramid_ids:
        pyramid_display, paginator, pyramid_page = get_paged_pyramids(caller_context.config, pyramid_ids, container_user, 10, int(active_page), int(active_position))

    return render_to_response('pyramids.html', locals())
def get_client_actions(request, caller_context, container_user):
    actions = {}
    
    #make sure we have a character
    if not container_user.character:
        actions['promptForCharacter'] = container_user.display_name
        return json_response(caller_context, container_user, actions, False)

    # check for daily gold bonus
    characterController = CharacterController()
    daily_gold = characterController.check_daily_reward(container_user)
    if daily_gold > 0:
        actions['dailyGold'] = daily_gold

    # get invites
    pyramidController = PyramidController()
    invited_pyramid_ids, invites = pyramidController.get_invited_pyramid_ids(container_user, True)
    if invites:
        actions['invites'] = {}
        for invite in invites:
            actions['invites'][invite.key().name()] = { "character_name" : invite.inviter_character.character_name, 
                                                        "inviterUrl" : invite.inviter_character.image_url }
            #startupJs += 'addToInviteQueue("%s", "%s", "%s");\n' % (invite.key().name(), invite.inviter_character.character_name, invite.inviter_character.image_url)
            
    # check for messages to player
    popup_messages = characterController.get_messages(container_user.character, 20, popup=True, unread=True)
    if popup_messages:
        actions['messages'] = {}
        for message in popup_messages:
            actions['messages'][message.key().name()] = { "title": message.title, 
                                                          "body" : message.body}
    characterController.mark_messages_read(popup_messages) # messages may not have actually been read, this would be better if confirmed via ajax callback
    
    if container_user.character.tutorial_on:
        actions["showTutorial"] = True

    include_experience_data = True
    return json_response(caller_context, container_user, actions, include_experience_data)
def join(request, caller_context, container_user, join_pyramid_id=None, join_brick_id=None, join_invite_key_name=None, action=None):
    ''' data only call, json response
    '''
    pyramidController = PyramidController()
    
    if join_invite_key_name:
        if action == 'accept':
            joinResult, joinInfo  = pyramidController.join_from_invite(caller_context.config, container_user, join_invite_key_name)
        elif action == 'decline':
            joinResult, joinInfo = pyramidController.decline_invite(container_user, join_invite_key_name)
    else:    
        joinResult, joinInfo  = pyramidController.join_pyramid(caller_context.config, int(join_pyramid_id), int(join_brick_id), container_user.character)
    
    joinResponse = { 'success' : joinResult, 
                      'result' : joinInfo}
    
    include_experience_data = False
    if joinResult:
        characterController = CharacterController()
        characterController.add_character_reward(container_user.character, "brick join", 'experience', 75)
        include_experience_data = True
    
    return json_response(caller_context, container_user, joinResponse, include_experience_data)
        except Exception, e:
            logging.exception(e)
            logging.warning('failed to roll forward transfer of Offerpal deposit')
    return response

def complete_uncommitted_actions(request, caller_context, container_user):
    accountController = AccountController()
    success = True
    try:
        transfer_count = accountController.execute_uncommitted_account_transfers(20)
    except Exception, e:
        success = False
        logging.error(e)
        
    try:
        pyramidController = PyramidController()
        join_count = pyramidController.execute_uncommitted_join_actions(20)
    except Exception, e:
        success = False
        logging.error(e)
    if success:
        return HttpResponse('rolled forward %d gold transfers and %d join actions' % (transfer_count, join_count))
    else:
        response = HttpResponse('exception completing uncommitted actions', status=500)
        return response
        
def expire_pyramids(request, caller_context, container_user):
    pyramidController = PyramidController()
    expired_count, warning_count = pyramidController.handle_expiring_pyramids(caller_context.config)
    if expired_count == 0 and warning_count == 0:
        return HttpResponse('nothing expired', 'text/html')