knatten / cppquiz

Source for the http://cppquiz.org website (not the questions)
GNU General Public License v3.0
102 stars 14 forks source link

Add the ability to get to the next sequential question #278

Open tocic opened 1 year ago

tocic commented 1 year ago

What do you think about adding a link that you can click to get to the next sequential question? For instance, if you've just answered the 305th question, you can now click either on the "Next unanswered random question" button or the "Next sequential question" button (offhand names). The latter will lead you to the 307th question, since there is no question numbered 306.

It might be useful in situations when you want to process all the questions one by one (e.g., you're cramming for a job interview or want to check existing question explanations before updating compiler explorer links :)). Currently, you can't just remember the last question you answered and continue where you left off the next day. And if you clear your local data on browser exit (nullify your session), it's hard to answer all the questions at all.

tocic commented 1 year ago

Or maybe even add more sophisticated navigation like this:

image

eoan-ermine commented 1 year ago

I agree, just today I was thinking about how useful this function would be

knatten commented 1 year ago

Yeah I've been thinking about this too, that it's currently hard to do all the questions on the site if you're for instance using multiple devices. I've been considering implementing a login system, but I have very little time to spend on developing the site further. And I haven't checked if GDPR would start applying or read up on how much work that would involve. If we implement a login system, it could be easier to integrate a good system for keeping track of progress. But I guess we could make a system now even without login, just tie it to the session, and then just adapt it to logged in users in the future if we implement login?

If we implement something like the navigation bar you suggest, what do we do about the current "next question" link when you've answered correctly and the current "try another question" link? Should they also go to the sequentially next question or to a random one? And what do we do when the user just visits cppquiz.org, which now redirects them to a random question, should it still do that, or redirect to question #1? I also think if we have the "first" and "last" links, a lot of people will go to the first question and start there.

I initially had some concerns about funnelling users to start at question 1, since I didn't bother citing the standard in the explanations back then, and feared that they are not of as high quality as the latter ones. But I looked through some of them now, and they are mostly pretty ok. It also seems I started citing the standard already in question 12. So maybe it's not so bad to start at question 1 always?

We also need to think about how this will fit with #5. If you've selected to only view questions of one or two difficulty levels, clicking next in your suggested navigation bar should probably then go to the sequentially next question which matches that/those level(s). Then it will be a bit hard to be a completionist, unless you first go through the entire site at one level, and then start over at the next level, but I guess that's ok?

tocic commented 1 year ago

@knatten I'm glad you like the idea. I've put together some design issues with my opinions for discussion:

  1. Does the navigation bar respect the user's progress?

I think the navigation bar should know nothing about the user data regardless of whether it's stored in an anonymous session or accounts DB. It should simply redirect you to https://cppquiz.org/quiz/question/id without a query string.

OK, but that means that if we've just answered some question, we will see it as a brand new question when navigating to it again!

Yes, and that's unfortunate IMO. Currently, you can reproduce this behaviour via manually typing the URL of an already answered question. Actually, it will not be completely new, since it'll show the number of attempts you've done, since this number is stored in your session. We also store the set of correct answers, and there's even a separate model (UsersAnswer) with all the required data to check if the requested question is already answered and display it as such. So I think we should change the question view behaviour: instead of querying the URL for did_answer we can just check the session or DB. Note that it'll break the current legit scenario: you can manually construct an answer URL specifying result, answer, and did_answer, and the page will be displayed as an answered question even if you haven't clicked the answer button before. I think this is fine. If you agree, I'll submit a separate PR.

With this change, we can even completely get rid of the URL query string, but it may break the users who rely on that API, so it's probably not worth it (though I checked the android app, and it just uses the static dump).

  1. What do we do about the current "next question" link when you've answered correctly and the current "try another question" link?

I think "go to a random question" is still as usuful behaviour as it was for users who want to just answer a few random questions. I'd leave the "try another question" link as is, as IMO it still fits perfectly in the "View a hint or try another question" sentence. For the "next question" link I see 2 possible changes: 1) rename to "next random question" or "next unanswered random question" (so it's clear how it's different from the next question in the navigation bar) or 2) integrate it into the navigation bar itself.

  1. What do we do when the user just visits cppquiz.org, which now redirects them to a random question?

I think it should still do that or redirect to a random question if it's the first visit, otherwise redirect to the last question that hasn't been answered. We can store this "current question" in a session or in an accounts DB (later). The first visit means the first visit for the session, not overall. We should postpone checking for the first visit overall until the login system is implemented, since I believe using an IP field from the UsersAnswer DB is error-prone (BTW, I'm afraid storing an undisguised IP isn't GDPR-compliant).

This latter scenario further facilitates the "continue where you left off" behaviour, and if you accidentally closed the site you can immediately return back. But it should be introduced as a separate PR too, since it's not directly connected to the navigation bar.

  1. How this will fit with #5?

I think the behaviour you described is totally expected and reasonable. We can incorporate filtering directly into the navigation bar via 3 checkboxes which are all checked by default. This way, you can select any combination of difficulties.

  1. Where exactly is the navigation bar located?

I think (1), (2) > (3), (4), since you can navigate even before answering a question; (1) > (2), since the navigation bar will stay in the same place regardless of the question length. And perhaps it should be aligned with the "Question #..." string, because why not?)

image

knatten commented 1 year ago

Simple things first:

I think it's a good idea to change the form from GET to POST. Then it also avoids people accidentally sharing a pre-answered URL if they just answered a question and want to send a link to others. And I don't think there are any good use cases for sharing a pre-answered question. A similar use case is for admins to share previews with question authors, but we have the preview functionality for that.

Then we can also change from checking did_answer to checking the session, I think that makes sense. The UsersAnswer is something I haven't touched since 2013, meant only for statistics iirc.

I think we could fix both of those as a separate PR, but I'd really like us to fix #280 first. (As mentioned in that issue, I think we should port these to regular system tests and not use a BDD framework.)

We don't need people's IP for anything, it's also something which has just been laying around since 2013 without much thought. I've made PR #292 to remove it.

As for the functionality itself:

One general comment first: I really want the site to be very simple to use for casual users. To me, that is more important than advanced use cases. So we should have that in mind whenever we introduce new functionality.

Next, I think we should be a bit more explicit here about the use cases / personas. Here are some I can think of (I think we can ignore the "fixed quiz" feature in this issue):

Casual users just wanting to take a few questions

For them, it's good the way the site is right now. Just get a random question, answer it (or skip it), and get to another random question.

If answering/skipping instead would send them to the next sequential question, that wouldn't really impact them at all. But if we always start at question 1, there's a disadvantage that they now always get the same questions if they visit the site from their home computer, their work computer and their phone for instance. With the random behaviour, the chance of this is much smaller. Therefore, I think it's important for this use case to always start on a random question.

Completionists who want to take all the questions

These want some way of taking all the questions on the site. If they always use the same device and never clear cookies, this works today. But if not, they don't really have any options today. So I think what we're trying to solve in this issue is the multi-device story for completionists. Agree? One way to solve this is to add something like the proposed navigation bar. Then they can remember which question ID they did last at home / at the commute or whatever, and pick it up from there on another device. Or just bookmark it or something. But I think this will only solve their use case in a good way if the various forms of "next question" links also take them to the sequentially next question. Otherwise it will be confusing when the "Next question" link takes them to a different question than the "next question" in the navigation bar would do, and maybe they don't even realise until they've been sent to a completely different place in the sequence a couple of times, and now they're lost.

Making a plan

While a navigation bar is a seemingly quite low effort idea to solve the completionist use case, let's first consider what would be the best way to solve it. I think that would be to have a login system. Then as long as people are logged in, they will have the same progress across all devices. It also avoids people having to remember IDs across devices, and removes any confusion about what "next question" means. Also, by not drawing people's attention to question IDs, it is less likely that they'll be confused about not all IDs being available. In my opinion it would be better to start on a login system than to start on a navigation bar.

So my proposal is to not do this issue at all, but rather start on a login system. I don't have time to think about this right now, so we'll have to get back to that in some months, and I also want to solve #280 first. Another thing I also think is more urgent than this, is to update the site from C++17. My plan is to skip C++20 and go directly to C++23. This will be a big effort, and I would rather focus resources on that. I've created #293 for this purpose.