[Userscript] The GanbarOmeter

Yes, please: rw at pobox.com.

The code throwing the error is this:

// calculate duration of reviews by peeking at next in sequence
// (duration is review-start to review-start)
// NOTE: doesn't change duration of final review in array
const calculateDuration = (r: Review, i: number, array: Review[]): Review => {
  if (array[i + 1]) {
    const nextms = array[i + 1].started.getTime();
    const thisms = r.started.getTime();
    if (nextms < thisms) {
      throw "Reviews not in sequential creation order!";
    }
    return { ...r, duration: nextms - thisms };
  } else {
    return r; // final review unchanged
  }
};

I’m not sure what undefined value I’m trying to filter, though. Will continue poking.

EDIT:

It’s from the section where I parse recent reviews. There must be something interesting with your data (thanks for the API key, that will help me to track it down). I suspect that it’s a level-60 thing! <laugh>

FWIW, I think it’s the first line of this section of code where I calculate the counts each day:

export const calculateCounts = (reviews: Review[]): ReviewCount[] => {
  const reviewsEachDay: Review[][] = reviews
    // first filter to one review per unique day
    .filter((r, i) =>
      i > 0 ? !inSameDay(r.started, reviews[i - 1].started) : true
    )
    // convert those reviews to just a date
    .map((r) => r.started)
    // finally, convert those dates to array of reviews on that date
    .map((date) => reviews.filter((r) => inSameDay(r.started, date)));

  let counts: ReviewCount[] = [];
  reviewsEachDay.forEach((reviewAry, i) => {
    const readingCorrect = reviewAry
      .filter((r) => r.reading_incorrect === 0)
      .reduce((acc, r) => (acc += 1), 0);
    const meaningCorrect = reviewAry
      .filter((r) => r.meaning_incorrect === 0)
      .reduce((acc, r) => (acc += 1), 0);
    const bothCorrect = reviewAry
      .filter((r) => r.meaning_incorrect + r.reading_incorrect === 0)
      .reduce((acc, r) => (acc += 1), 0);

    const questionCount = reviewAry.reduce((acc, r) => (acc += r.questions), 0);
    const itemCount = reviewAry.length;
    const count: ReviewCount = {
      start: reviewAry[0].started,
      end: reviewAry[reviewAry.length - 1].started,
      review_count: reviewAry.length,
      question_count: questionCount,
      accuracy: bothCorrect / itemCount,
      reading_accuracy: readingCorrect / itemCount,
      meaning_accuracy: meaningCorrect / itemCount,
    };
    counts.push(count);
  });
  return counts;
};
1 Like

Sent

Do you account for people using offline review apps which may submit reviews arbitrarily far in the past (as long as the review was available at that time, of course)?

Heh. That would be a “no”. :slight_smile:

I definitely expected reviews to be in created in sequential order (and returned from the API in the same order). It never occurred to me that other scripts might invalidate that assumption.

I need to think about this for a bit.

1 Like

Since you’re only fetching a few days worth of data it would be pretty quick to just sort the reviews after fetching them

Great minds think alike. :wink:

Give me a bit and I’ll post a version for you to try that does exactly that.

1 Like

My brain isn’t working today. I’m also unfamiliar with offline review scripts.

Should I be sorting based on some_review.data_updated_at or some_review.data.created_at?

These have always been pretty close to the same for me, but I’m curious about the review records the scripts create — can the values diverge? I want the day/time the most recent review occurred.

1 Like

I believe you want to sort by created_at. When you create a review record updated_at is automatically set to the current time (so that you can query based on when a record was updated), whereas created_at can be specified

see WaniKani API Reference

1 Like

Hmm…

The way the script works is to query the API for review records that were updated after a specific date (n days ago, where n is between 1 and 7).

I need to look at the reviews returned by your API key, but I’m trying to understand what the offline review scripts do. Can you point me at such a script (I’m totally unfamiliar with how they work)?

If I retrieve 7 days of reviews, is it possible I’ll get back a review with a created_at date more than 7 days ago (even though data_updated_at is within the window)?

Since I’m trying to display a bar for each day the review was PERFORMED, I think (but I’m not sure) it makes the most sense to use the update date.

(EDIT: I think I get it. “Offline” in the sense of doing reviews in another app, then pushing all those reviews to the server when back online. The created_at dates are indeed when the review was performed, but order returned from the API is most likely when the records were updated. It’s possible for someone to do some reviews online, then several offline, then some online, THEN push the updates from the offline session. I need to first filter out reviews with created_at outside the window, then sort by created_at.)

1 Like

This is sufficient to fetch all the reviews performed in the last n days, but you may need to filter out older reviews and sort remaining reviews.

The idea is that you can do your reviews offline. When you do the review the apps saves the time you did it as the created_at date. When you come back online the app submits the review with the created_at date in the past. The review will have a updated_at date for the time it was submitted.

One is Flaming Durtles, but I don’t know if the source code is available. All you need to know, however, is that the created_at date can be way in the past. If I had reviews due from two years ago I could submit those reviews as having been done two years ago, but they would be marked as updated today.

Yes, so you need to filter and sort the reviews

yes!

1 Like

Got it! Thanks.

Can I make the assertion that created_at cannot be more recent than data_updated_at? As long as that holds true I think this will be a fairly straightforward fix.

1 Like

Yeah, I don’t think that should ever be a case (you can’t create future reviews)

1 Like

When you have a moment, could you try the dev version I just pushed up:

https://raw.githubusercontent.com/wrex/ganbarometer-svelte/main/published/dev/bundle.js
1 Like

No error and it loads as expected! Is this supposed to be 0, though? It was before as well

image

Yay. Progress.

Can you post the Data view? Not sure what’s going on there.

(P.S. I think @Lupo_Mikti should hire you in QA)

1 Like

Hmm. Data shows 1 review those days. Let me use your api key to see if it should be zero.

Give me a bit - grabbing a bite.

1 Like

Pretty sure it should be 1. Whenever I don’t do any reviews in a day I try to at least do 1 to remind myself. Easier to stay on the horse that way

1 Like

Oh! You are talking about the value lavels on the left showing zero. That’s definitely a bug. I thought you meant the two short bars.

1 Like

Haha, yes, sorry about that