'Ensure that map, reduce, and finalize run and introduce "scope"
by simulating "hotness" ranking with Reddit algorithm.'

def test_map_reduce_finalize(self):

    from time import mktime
    class Link(Document, ):
        title = StringField(db_field='bpTitle')
        up_votes = IntField()
        down_votes = IntField()
        submitted = DateTimeField(db_field='sTime')
    Link.drop_collection()
    now = datetime.datetime.utcnow()
    Link(title="Google    Buzz    auto-followed    a    woman's    abusive    ex    ...", up_votes=1079, down_votes=553, submitted=(now - datetime.timedelta(hours=4))).save()
    Link(title='We    did    it!    Barbie    is    a    computer    engineer.', up_votes=481, down_votes=124, submitted=(now - datetime.timedelta(hours=2))).save()
    Link(title='This    Is    A    Mosquito    Getting    Killed    By    A    Laser', up_votes=1446, down_votes=530, submitted=(now - datetime.timedelta(hours=13))).save()
    Link(title='Arabic    flashcards    land    physics    student    in    jail.', up_votes=215, down_votes=105, submitted=(now - datetime.timedelta(hours=6))).save()
    Link(title='The    Burger    Lab:    Presenting,    the    Flood    Burger', up_votes=48, down_votes=17, submitted=(now - datetime.timedelta(hours=5))).save()
    Link(title='How    to    see    polarization    with    the    naked    eye', up_votes=74, down_votes=13, submitted=(now - datetime.timedelta(hours=10))).save()
    map_f = '\n                                                function()    {\n                                                                emit(this[~id],    {up_delta:    this[~up_votes]    -    this[~down_votes],\n                                                                                                                                sub_date:    this[~submitted].getTime()    /    1000})\n                                                }\n                                '
    reduce_f = "\n                                                function(key,    values)    {\n                                                                data    =    values[0];\n\n                                                                x    =    data.up_delta;\n\n                                                                //    calculate    time    diff    between    reddit    epoch    and    submission\n                                                                sec_since_epoch    =    data.sub_date    -    reddit_epoch;\n\n                                                                //    calculate    'Y'\n                                                                if(x    >    0)    {\n                                                                                y    =    1;\n                                                                }    else    if    (x    =    0)    {\n                                                                                y    =    0;\n                                                                }    else    {\n                                                                                y    =    -1;\n                                                                }\n\n                                                                //    calculate    'Z',    the    maximal    value\n                                                                if(Math.abs(x)    >=    1)    {\n                                                                                z    =    Math.abs(x);\n                                                                }    else    {\n                                                                                z    =    1;\n                                                                }\n\n                                                                return    {x:    x,    y:    y,    z:    z,    t_s:    sec_since_epoch};\n                                                }\n                                "
    finalize_f = '\n                                                function(key,    value)    {\n                                                                //    f(sec_since_epoch,y,z)    =\n                                                                //                                                                                log10(z)    +    ((y*sec_since_epoch)    /    45000)\n                                                                z_10    =    Math.log(value.z)    /    Math.log(10);\n                                                                weight    =    z_10    +    ((value.y    *    value.t_s)    /    45000);\n                                                                return    weight;\n                                                }\n                                '
    reddit_epoch = mktime(datetime.datetime(2005, 12, 8, 7, 46, 43).timetuple())
    scope = {'reddit_epoch': reddit_epoch}
    results = Link.objects.order_by('-value')
    results = results.map_reduce(map_f, reduce_f, 'myresults', finalize_f=finalize_f, scope=scope)
    results = list(results)
    self.assertTrue(results[0].object.title.startswith('Google    Buzz'))
    self.assertTrue(results[(-1)].object.title.startswith('How    to    see'))
    Link.drop_collection()
