docs: def user_stats(request):
      """
      Get user statistics for selected groups of items
  
      time:
        time in format '%Y-%m-%d_%H:%M:%S' used for practicing
      user:
        identifier of the user (only for stuff users)
      username:
        username of user (only for users with public profile)
      filters:                -- use this or body
        json as in BODY
      mastered:
        use model to compute number of mastered items - can be slowed
      language:
        language of the items
  
      BODY
        json in following format:
        {
          "#identifier": []         -- custom identifier (str) and filter
          ...
        }
      """
      timer('user_stats')
      response = {}
      data = None
      if request.method == "POST":
          data = json.loads(request.body.decode("utf-8"))["filters"]
      if "filters" in request.GET:
          data = load_query_json(request.GET, "filters")
      if data is None:
          return render_json(request, {}, template='models_user_stats.html', help_text=user_stats.__doc__)
      environment = get_environment()
      if is_time_overridden(request):
          environment.shift_time(get_time(request))
      user_id = get_user_id(request)
      language = get_language(request)
      filter_names, filter_filters = list(zip(*sorted(data.items())))
      reachable_leaves = Item.objects.filter_all_reachable_leaves_many(filter_filters, language)
      all_leaves = sorted(list(set(flatten(reachable_leaves))))
      answers = environment.number_of_answers_more_items(all_leaves, user_id)
      correct_answers = environment.number_of_correct_answers_more_items(all_leaves, user_id)
      if request.GET.get("mastered"):
          timer('user_stats_mastered')
          mastery_threshold = get_mastery_trashold()
          predictions = Item.objects.predict_for_overview(environment, user_id, all_leaves)
          mastered = dict(list(zip(all_leaves, [p >= mastery_threshold for p in predictions])))
          LOGGER.debug("user_stats - getting predictions for items took %s seconds", (timer('user_stats_mastered')))
      for identifier, items in zip(filter_names, reachable_leaves):
          if len(items) == 0:
              response[identifier] = {
                  "filter": data[identifier],
                  "number_of_items": 0,
              }
          else:
              response[identifier] = {
                  "filter": data[identifier],
                  "number_of_items": len(items),
                  "number_of_practiced_items": sum(answers[i] > 0 for i in items),
                  "number_of_answers": sum(answers[i] for i in items),
                  "number_of_correct_answers": sum(correct_answers[i] for i in items),
              }
              if request.GET.get("mastered"):
                  response[identifier]["number_of_mastered_items"]= sum(mastered[i] for i in items)
      return render_json(request, response, template='models_user_stats.html', help_text=user_stats.__doc__)