Esempio n. 1
0
def setlesson(request,lesson_id):
    """Adds this lesson to the active deck.
    """

    # put this lesson into the model
    model = get_model(request)
    if model is None:
        resetdeck(request)
        model = get_model(request)
    model.set_active_lesson(lesson_id)
    save_model(request, model)

    # send them off to study
    return HttpResponseRedirect("/study/")
Esempio n. 2
0
def setlesson(request, lesson_id):
    """Adds this lesson to the active deck.
    """

    # put this lesson into the model
    model = get_model(request)
    if model is None:
        resetdeck(request)
        model = get_model(request)
    model.set_active_lesson(lesson_id)
    save_model(request, model)

    # send them off to study
    return HttpResponseRedirect("/study/")
Esempio n. 3
0
def impression(request):
    """Logs that the user had an impression of a card.
    This is called frequently by the studyui.
    Turns user action into an Impression object.
    """

    # For testing slow/unreliable server...
    #time.sleep(3)

    # put this into a database table...
    i = Impression()
    #print request.POST
    i.answer = request.POST['answer']
    i.concept_id = long(request.POST['id'])
    i.user = request.user
    i.timer_show = request.POST.get('showtimer')
    i.timer_submit = request.POST.get('submittimer')
    i.save()

    #print "times: %s,%s ms" % (request.POST['showtime'], request.POST['submittime'])

    # tell the learning model about the impression
    model = get_model(request)
    concept = model.log_impression(i)
    save_model(request, model)

    # return a simple HTTP response
    return HttpResponse("OK", mimetype='text/plain')
Esempio n. 4
0
def jsondeck(request):
    """Renders the entire deck in JSON for use with the dnd deckview
    """

    model = get_model(request)
    data = {}
    for pile in model.supported_piles():
        data[pile]=[]
        for card in model.cards_in_pile(pile):
            ert = model._get_card_metadata(card,'ert')  #TODO: Not portable!
            next_exposure_str = None
            if ert:
                impression = card.history().lookup_last_impression()
                if impression: 
                    next_exposure = impression.answered_date + datetime.timedelta(seconds = ert)
                    next_exposure_str = str(next_exposure - datetime.datetime.now())
            datum = {'card': card.json(),
                     'ert': ert,
                     'next': next_exposure_str,
                    }
            data[pile].append( datum )

    return HttpResponse(
                    json.dumps(data),
                    mimetype='text/plain'
                    )
Esempio n. 5
0
def get_many_qa(request, numcards):
    """Fetches the next 'numcard' cards to be displayed. Similar to getqa.
    Returns a json array, with the first element being the sequence number
    and each subsequent element being a json card object.
    Allows smart client to pre-fetch multiple cards to minimize user latency.
    Guaranteed not to modify the model state -- it won't be saved!
    """

    # For testing slow/unreliable server...
    #time.sleep(3)
    #if random.uniform(0,1) < 0.5:
    #raise NotImplmentedError()

    # manually casting seems to avoid unicode wierdness
    numcards = int(numcards)

    model = get_model(request)

    # stash the sequence number at the beginning
    data = [model.get_sequence()]

    # ask the model for all the cards to show
    cards = model.choose_many_cards(numcards)

    for card in cards:
        data.append(card.json())

    return HttpResponse(json.dumps(data), mimetype='text/plain')
Esempio n. 6
0
def impression(request):
    """Logs that the user had an impression of a card.
    This is called frequently by the studyui.
    Turns user action into an Impression object.
    """

    # For testing slow/unreliable server...
    #time.sleep(3)

    # put this into a database table...
    i = Impression()
    #print request.POST
    i.answer = request.POST['answer']
    i.concept_id = long(request.POST['id'])
    i.user = request.user
    i.timer_show = request.POST.get('showtimer')
    i.timer_submit = request.POST.get('submittimer')
    i.save()

    #print "times: %s,%s ms" % (request.POST['showtime'], request.POST['submittime'])

    # tell the learning model about the impression
    model = get_model(request)
    concept = model.log_impression(i)
    save_model(request, model)

    # return a simple HTTP response
    return HttpResponse("OK", mimetype='text/plain')
Esempio n. 7
0
def get_many_qa(request,numcards):
    """Fetches the next 'numcard' cards to be displayed. Similar to getqa.
    Returns a json array, with the first element being the sequence number
    and each subsequent element being a json card object.
    Allows smart client to pre-fetch multiple cards to minimize user latency.
    Guaranteed not to modify the model state -- it won't be saved!
    """

    # For testing slow/unreliable server...
    #time.sleep(3)
    #if random.uniform(0,1) < 0.5:
        #raise NotImplmentedError()

    # manually casting seems to avoid unicode wierdness
    numcards = int(numcards)

    model = get_model(request)

    # stash the sequence number at the beginning
    data = [ model.get_sequence() ]

    # ask the model for all the cards to show
    cards = model.choose_many_cards(numcards)

    for card in cards:
        data.append( card.json() )

    return HttpResponse(
                    json.dumps(data),
                    mimetype='text/plain'
                    )
Esempio n. 8
0
def dnddeckview(request):
    """Shows the old drag-n-drop deck view which doesn't do much
    """

    model = get_model(request)
    return render_to_response("deck/dnddeck.html", {
                    'piles': model.supported_piles(),
                }, context_instance=RequestContext(request))
Esempio n. 9
0
def debugmodel(request):
    """Dumps out the model in human-readable form.
    Also displays a form for allowing the debugger to post an impression and see
    any error message
    """

    model = get_model(request)
    str = u"%s" % model
    return render_to_response("study/debug.html", {'debugstring': str})
Esempio n. 10
0
def debugmodel(request):
    """Dumps out the model in human-readable form.
    Also displays a form for allowing the debugger to post an impression and see
    any error message
    """

    model = get_model(request)
    str = u"%s" % model
    return render_to_response("study/debug.html", { 'debugstring': str } )
Esempio n. 11
0
def jsoncard(request, card_id):
    """Renders JSON for a single card
    TODO: HTTP-cache these, since they're immutable
    (This is not actually used...)
    """

    model = get_model(request)
    card = Card.lookup_card(card_id)
    data = card.json()
    return HttpResponse(json.dumps(data), mimetype='text/plain')
Esempio n. 12
0
def studyui(request):
    """Shows the UI which presents cards and solicits the responses.
    This UI is all ajaxy and doesn't need any server-side data.
    #TODO: move this to static media
    """

    if get_model(request) is None:
        #TODO: generalize this to send you to a 'pick a lesson' page
        return HttpResponseRedirect("/chinese/")

    return render_to_response("study/studyui.html", context_instance=RequestContext(request))
Esempio n. 13
0
def studyui(request):
    """Shows the UI which presents cards and solicits the responses.
    This UI is all ajaxy and doesn't need any server-side data.
    #TODO: move this to static media
    """

    if get_model(request) is None:
        #TODO: generalize this to send you to a 'pick a lesson' page
        return HttpResponseRedirect("/chinese/")

    return render_to_response("study/studyui.html",
                              context_instance=RequestContext(request))
Esempio n. 14
0
def jsoncard(request, card_id):
    """Renders JSON for a single card
    TODO: HTTP-cache these, since they're immutable
    (This is not actually used...)
    """

    model = get_model(request)
    card = Card.lookup_card(card_id)
    data = card.json()
    return HttpResponse(
                    json.dumps(data),
                    mimetype='text/plain'
                    )
Esempio n. 15
0
def debug_card(request,card_id):
    card = Card.lookup_card(card_id)
    model = get_model(request)
    history = card.history()
    params = {}
    params['pile'] = model.which_pile(card)
    params['ert'] = safe_timedelta(seconds = model.get_ert(card))
    params['estimated_ert'] = safe_timedelta(model._estimate_ert(card))
    params['longest_yes'] = history.delay_on_longest_yes()
    params['most_recent_yes'] = history.delay_on_most_recent_yes()[0]
    params['how_far_back_most_recent_yes'] = history.delay_on_most_recent_yes()[1]
    params['next_exposure'] = model.next_exposure_date(card)
    params['last_exposure'] = history.lookup_last_impression()
    params['answer_history'] = history.full_impression_history(20)

    return render_to_response("deck/debug_card.html", params, 
            context_instance=RequestContext(request))
Esempio n. 16
0
def getqa(request):
    """Returns the next card to display to the user.
    This is called frequently by the studyui.
    Guaranteed not to modify the model state -- it won't be saved!
    """

    # call the model to pick the next card to show
    model = get_model(request)
    card = model.choose_card()

    # Note: I'm changing the contract here.
    # Models aren't allowed to change their state when picking a card.
    # Picking a card has no side-effects.
    # This is not a big burden on the model, but greatly simplifies
    # the client.
    #save_model(request, model)

    data = card.json()
    return HttpResponse(json.dumps(data), mimetype='text/plain')
Esempio n. 17
0
def show_meta(request):
    # first, fetch the recent impressions
    recent_impressions = Impression.objects.order_by('-answered_date').filter(user=request.user)
    # limit to last 30 impressions
    recent_impressions = recent_impressions[0:29]

    # now build a list of card Q's, with the pile for each card. 
    # don't eliminate duplicate cards
    model = get_model(request)
    recent_cards = []
    for impression in recent_impressions:
        #print "id %s" % impression.concept.id
        card = Card.lookup_card(impression.concept.id)

        pile = model.which_pile(card)
        ert = model._get_card_metadata(card,'ert')  #TODO: Not portable!
        logging.debug("ert for %s is %s" % (card,ert))
        if ert:
            next_exposure = impression.answered_date + datetime.timedelta(seconds = ert)
        else:
            next_exposure = None
        recent_cards.append( (card.question(), pile, card, ert, next_exposure) )

    #
    # fetch counts for each pile
    #
    pilecount = []
    for pile in model.supported_piles():
        pilecount.append( (pile, len( model.cards_in_pile(pile) ) ) )

    # and the description
    description = model.description

    templatevars = {
        'recent_cards': recent_cards,
        'pilecount': pilecount,
        'description': description,
        }

    return render_to_response("deck/show_meta.html", templatevars)
Esempio n. 18
0
def getqa(request):
    """Returns the next card to display to the user.
    This is called frequently by the studyui.
    Guaranteed not to modify the model state -- it won't be saved!
    """

    # call the model to pick the next card to show
    model = get_model(request)
    card = model.choose_card()

    # Note: I'm changing the contract here.
    # Models aren't allowed to change their state when picking a card.
    # Picking a card has no side-effects.
    # This is not a big burden on the model, but greatly simplifies
    # the client.
    #save_model(request, model)

    data = card.json()
    return HttpResponse(
                    json.dumps(data),
                    mimetype='text/plain'
                    )
Esempio n. 19
0
def deckview(request):
    """Shows you a list of recent cards.
    """

    # first, fetch the recent impressions
    recent_impressions = Impression.objects.order_by('-answered_date').filter(user=request.user)
    # limit to last 30 impressions
    recent_impressions = recent_impressions[0:29]

    # now build a list of card Q's, with the pile for each card. 
    # don't eliminate duplicate cards
    model = get_model(request)
    recent_cards = []
    for impression in recent_impressions:
        #print "id %s" % impression.concept.id
        card = Card.lookup_card(impression.concept.id)

        pile = model.which_pile(card)
        recent_cards.append( (card.question(), pile, card) )

    #
    # fetch counts for each pile
    #
    pilecount = []
    for pile in model.supported_piles():
        pilecount.append( (pile, len( model.cards_in_pile(pile) ) ) )

    # and the description
    description = model.description

    templatevars = {
        'recent_cards': recent_cards,
        'pilecount': pilecount,
        'description': description,
        }

    return render_to_response("deck/deckview.html", templatevars)
Esempio n. 20
0
def create_review_deck(request):
    """ Creates a deck forreviewing old material.
    Wipes out the current deck 
    """

    # start over with a new model
    resetdeck(request)
    model = get_model(request)

    # Fetch a bunch of impressions
    all_no = Impression.objects.filter(user=request.user, answer="No")
    all_kinda = Impression.objects.filter(user=request.user, answer="Kinda")

    # add up the bad impressions
    bad_total = {}
    for impression in all_kinda:
        id = impression.concept_id
        # TUNE: 1 point per kinda
        if id not in bad_total:
            bad_total[ impression.concept_id ] = 1
        else:
            bad_total[ impression.concept_id ] += 1
    for impression in all_no:
        id = impression.concept_id
        # TUNE: 3 points per no
        if id not in bad_total:
            bad_total[ impression.concept_id ] = 3
        else:
            bad_total[ impression.concept_id ] += 3

    # invert the map so it maps # bad points to concepts.
    # Note there could be collisions here, so build a list for each num pts
    inverted_bad_total = {}
    for id, pts in bad_total.items():
        # TUNE: Minimum threshhold for something to be reviewable
        if pts > 2:
            if pts not in inverted_bad_total:
                inverted_bad_total[pts]=[id]
            else:
                inverted_bad_total[pts].append(id)
    
    # Prepare results list
    review_cards = []

    # Now we put together our list of cards, in order of badness
    #print "ibt: %s" % inverted_bad_total
    pts_order_desc = inverted_bad_total.keys()
    pts_order_desc.reverse()
    #print "pod: %s" % pts_order_desc
    for pts in pts_order_desc:
        for card in inverted_bad_total[pts]:
            review_cards.append(card)
        
    # Now put them all into the model
    model.add_new_cards("Review of difficult cards", review_cards)

    # Write the model back
    save_model(request,model)

    # redirect to a standard deck view
    return HttpResponseRedirect("/deck/")