from flashcards.models import (FactType, Fact, Deck, CardTemplate, FieldType, FieldContent, Card, GRADE_NONE, GRADE_HARD, GRADE_GOOD, GRADE_EASY) from django.template.loader import render_to_string import datetime def subfact_form_context(request, subfact=None, field_content_offset=0, fact_form_ordinal=1): ''' `form_ordinal` is the offset to use for e.g. fact-1-id ''' context = {} sentence_fact_type = FactType.objects.get(id=2) field_types = sentence_fact_type.fieldtype_set.exclude( disabled_in_form=True).order_by('ordinal') context.update({ 'fact_type': sentence_fact_type, 'field_types': field_types, }) if subfact: context.update({ 'field_content_for_field_types': dict((field_type, subfact.field_contents.get(field_type=field_type),) for field_type in field_types), 'field_content_offset': field_content_offset, 'fact_form_ordinal': fact_form_ordinal, 'is_js_template': False, 'subfact': subfact, }) else: context.update({ 'is_js_template': True, }) return {'subfact_form': context} def fact_add_form_context(request, deck=None, autofocus=False, popup_window=False, takes_initial_values_from_GET=False): context = {} fact_type = FactType.objects.japanese card_templates = fact_type.cardtemplate_set.all() field_types = fact_type.fieldtype_set.exclude( disabled_in_form=True).order_by('ordinal') # Get any initial form values from the GET params. # They'll be sanitized in the template. for field_type in field_types: if takes_initial_values_from_GET: field_type.initial = request.GET.get(field_type.name, None) else: field_type.initial = None context['fact_add_form'] = { 'card_templates': card_templates, 'field_types': field_types, 'deck': deck, 'autofocus': autofocus, 'popup_window': popup_window, } context.update(subfact_form_context(request)) return context def card_existence_context(request): ''' adds 'cards_exist', 'decks_exist' (booleans) ''' ctx = {} if request.user.is_authenticated(): decks = Deck.objects.of_user(request.user) cards = Card.objects.of_user(request.user, with_upstream=True) ctx = { 'decks_exist': decks.exists(), 'cards_exist': cards.exists(), } return ctx def deck_count_context(request): ''' adds `deck_count` ''' deck_count = Deck.objects.of_user(request.user).count() return {'deck_count': deck_count} def review_start_context(request, deck=None): ''' Returns a dictionary for studying either all decks, or a single deck. This is for the screen before actually reviewing, which shows the buttons to start the review. ''' user = request.user cards = Card.objects.common_filters(user, with_upstream=True, deck=deck) due_card_count = cards.due(user).count() new_card_count = cards.new_count(user) card_count = cards.count() # this is much faster but less accurate than cards.unspaced_new_count. unspaced_new_card_count = cards.approx_new_count(user) context = { 'card_count': card_count, 'next_card_due_at': cards.next_card_due_at(), 'due_card_count': due_card_count, 'new_card_count': new_card_count, 'can_learn_more': new_card_count > 0, 'is_early_review': ( due_card_count == 0 and card_count and unspaced_new_card_count == 0), #and card_count != new_card_count), 'count_of_cards_due_tomorrow': cards.count_of_cards_due_tomorrow(user), 'unspaced_new_card_count': unspaced_new_card_count, } context['next_card_due_at_message'] = render_to_string( 'flashcards/_next_card_due_at.txt', context).strip() #'new_cards_left_for_today': new_cards_left_for_today, return context #def study_options_context(request, deck_id=None): # ''' # Returns a dictionary for studying either all decks, or a single deck. # DEPRECATED # ''' # context = {} # deck = Deck.objects.get(id=deck_id) if deck_id else None # deck_count = Deck.objects.of_user(request.user).count() # next_card_due_at = Card.objects.next_card_due_at(request.user, deck=deck) # if next_card_due_at: # time_until_next_card_due = next_card_due_at - datetime.datetime.utcnow() # context.update({ # 'next_card_due_at': next_card_due_at, # 'time_until_next_card_due': time_until_next_card_due, # 'minutes_until_next_card_due': time_until_next_card_due.days * 24 + time_until_next_card_due.seconds / 60, # 'hours_until_next_card_due': time_until_next_card_due.days * 24 + time_until_next_card_due.seconds / (60 * 60), # }) # # New card count for today. # # estimate adjusted count of new cards that can be reviewed now, after spacing, by just counting the unique facts # daily_new_card_limit = NEW_CARDS_PER_DAY # if deck or deck_count: # due_card_count = Card.objects.due_cards(request.user, deck=deck).count() # new_card_count = Card.objects.new_cards(request.user, deck=deck).count() # new_reviews_today = request.user.reviewstatistics.get_new_reviews_today() # if daily_new_card_limit: # spaced_new_card_count = Card.objects.next_cards_count(request.user, deck=deck, new_cards_only=True) # if spaced_new_card_count: # new_cards_left_for_today = daily_new_card_limit - new_reviews_today # if new_cards_left_for_today < 0: # new_cards_left_for_today = 0 # new_cards_left_for_today = min(new_cards_left_for_today, spaced_new_card_count) # else: # new_cards_left_for_today = 0 # #context['can_learn_more'] = new_cards_left_for_today > 0 # else: # new_cards_left_for_today = None # context['can_learn_more'] = new_card_count > 0 # context.update({ # 'is_early_review': due_card_count == 0 and new_cards_left_for_today == 0, # 'card_count': Card.objects.of_user(request.user).count(), # 'due_card_count': due_card_count, # 'new_card_count': new_card_count, # #'spaced_new_card_count': spaced_new_card_count, # 'count_of_cards_due_tomorrow': Card.objects.count_of_cards_due_tomorrow(request.user, deck=deck), # 'new_cards_left_for_today': new_cards_left_for_today, # }) # # is this (not) a request for a specific deck? # if not deck_id: # context.update({ # 'deck_count': deck_count, # }) # return context