예제 #1
0
 /** Return one card starting from the given cursor. */
 private static Card oneFromCursor(Cursor cursor) {
   if (cursor.isClosed()) {
     throw new SQLException();
   }
   cursor.moveToFirst();
   Card card = new Card();
   card.id = cursor.getLong(0);
   card.interval = cursor.getDouble(1);
   card.question = cursor.getString(2);
   card.answer = cursor.getString(3);
   return card;
 }
예제 #2
0
  public void answerCard(Card card, int ease) {
    Cursor cursor = null;
    String undoName = "Answer Card";
    setUndoStart(undoName);
    double now = System.currentTimeMillis() / 1000.0;

    // Old state
    String oldState = cardState(card);
    double lastDelaySecs = System.currentTimeMillis() / 1000.0 - card.combinedDue;
    double lastDelay = lastDelaySecs / 86400.0;
    int oldSuc = card.successive;

    // update card details
    double last = card.interval;
    card.interval = nextInterval(card, ease);
    if (lastDelay >= 0) card.lastInterval = last; // keep last interval if reviewing early
    if (card.reps != 0) card.lastDue = card.due; // only update if card was not new
    card.due = nextDue(card, ease, oldState);
    card.isDue = 0;
    card.lastFactor = card.factor;
    if (lastDelay >= 0) updateFactor(card, ease); // don't update factor if learning ahead

    // spacing
    double space, spaceFactor, minSpacing, minOfOtherCards;
    try {
      cursor =
          AnkiDb.database.rawQuery(
              "SELECT models.initialSpacing, models.spacing "
                  + "FROM facts, models "
                  + "WHERE facts.modelId = models.id and "
                  + "facts.id = "
                  + card.factId,
              null);
      if (!cursor.moveToFirst()) {
        minSpacing = 0;
        spaceFactor = 0;
      } else {
        minSpacing = cursor.getDouble(0);
        spaceFactor = cursor.getDouble(1);
      }
    } finally {
      if (cursor != null) cursor.close();
    }

    try {
      cursor =
          AnkiDb.database.rawQuery(
              "SELECT min(interval) "
                  + "FROM cards "
                  + "WHERE factId = "
                  + card.factId
                  + " and id != "
                  + card.id,
              null);
      if (!cursor.moveToFirst()) minOfOtherCards = 0;
      else minOfOtherCards = cursor.getDouble(0);
    } finally {
      if (cursor != null) cursor.close();
    }
    if (minOfOtherCards != 0) space = Math.min(minOfOtherCards, card.interval);
    else space = 0;
    space = space * spaceFactor * 86400.0;
    space = Math.max(minSpacing, space);
    space += System.currentTimeMillis() / 1000.0;
    card.combinedDue = Math.max(card.due, space);

    // check what other cards we've spaced
    String extra;
    if (this.reviewEarly) extra = "";
    else {
      // if not reviewing early, make sure the current card is counted
      // even if it was not due yet (it's a failed card)
      extra = "or id = " + card.id;
    }

    try {
      cursor =
          AnkiDb.database.rawQuery(
              "SELECT type, count(type) "
                  + "FROM cards "
                  + "WHERE factId = "
                  + card.factId
                  + " and "
                  + "(isDue = 1 "
                  + extra
                  + ") "
                  + "GROUP BY type",
              null);
      while (cursor.moveToNext()) {
        if (cursor.getInt(0) == 0) failedSoonCount -= cursor.getInt(1);
        else if (cursor.getInt(0) == 1) revCount -= cursor.getInt(1);
        else newCount -= cursor.getInt(1);
      }
    } finally {
      if (cursor != null) cursor.close();
    }

    // space other cards
    AnkiDb.database.execSQL(
        String.format(
            ENGLISH_LOCALE,
            "UPDATE cards "
                + "SET spaceUntil = %f, "
                + "combinedDue = max(%f, due), "
                + "modified = %f, "
                + "isDue = 0 "
                + "WHERE id != %d and factId = %d",
            space,
            space,
            now,
            card.id,
            card.factId));
    card.spaceUntil = 0;

    // temp suspend if learning ahead
    if (reviewEarly && lastDelay < 0)
      if (oldSuc != 0 || lastDelaySecs > delay0 || !showFailedLast()) card.priority = -1;
    // card stats
    card.updateStats(ease, oldState);

    card.toDB();

    // global/daily stats
    Stats.updateAllStats(this.globalStats, this.dailyStats, card, ease, oldState);

    // review history
    CardHistoryEntry entry = new CardHistoryEntry(card, ease, lastDelay);
    entry.writeSQL();
    modified = now;
    //        // TODO: Fix leech handling
    //        if (isLeech(card))
    //            card = handleLeech(card);
    setUndoEnd(undoName);
  }