+ translate: translate,
+ firstFetch: function() {
+ // Fetch most recent problems from server, for both lists
+ this.fetchProblems("others", "bacwkard");
+ this.fetchProblems("mine", "bacwkard");
+ this.listsInitialized = true;
+ },
+ showProblem: function(pid) {
+ location.hash = "#problems?id=" + pid;
+ for (let parray of [this.singletons,this.problems,this.myProblems])
+ {
+ const pIdx = parray.findIndex(p => p.id == pid);
+ if (pIdx >= 0)
+ {
+ this.curProb = parray[pIdx];
+ break;
+ }
+ }
+ if (!this.curProb)
+ {
+ // Cannot find problem in current set; get from server, and add to singletons.
+ ajax(
+ "/problems/" + variant.id + "/" + pid, //TODO: variant ID should not be required
+ "GET",
+ response => {
+ if (!!response.problem)
+ {
+ this.singletons.push(response.problem);
+ this.curProb = response.problem;
+ this.display = (response.problem.uid == this.userId ? "mine" : "others");
+ }
+ else
+ this.noMoreProblems("Sorry, problem " + pid + " does not exist");
+ }
+ );
+ }
+ else
+ this.display = (this.curProb.uid == this.userId ? "mine" : "others");
+ },
+ curProblems: function() {
+ switch (this.display)
+ {
+ case "others":
+ return this.problems;
+ case "mine":
+ return this.myProblems;
+ }
+ },
+ // TODO?: get 50 from server but only show 10 at a time (for example)
+ showNext: function(direction) {
+ const nomorePb =
+ problems => {
+ if (!problems || problems.length == 0)
+ this.noMoreProblems("No more problems in this direction");
+ };
+ if (!this.curProb)
+ return this.fetchProblems(this.display, direction, nomorePb);
+ // Show next problem (older or newer):
+ let curProbs = this.curProblems();
+ // Try to find a neighbour problem in the direction, among current set
+ const neighbor = this.findClosestNeighbor(this.curProb, curProbs, direction);
+ if (!!neighbor)
+ {
+ this.curProb = neighbor;
+ return;
+ }
+ // Boundary case: nothing in current set, need to fetch from server
+ const curSize = curProbs.length;
+ this.fetchProblems(this.display, direction, problems => {
+ if (problems.length > 0)
+ {
+ // Ok, found something:
+ this.curProb =
+ this.findClosestNeighbor(this.curProb, curProbs, direction);
+ }
+ else
+ nomorePb();
+ });
+ },
+ findClosestNeighbor: function(problem, probList, direction) {
+ let neighbor = undefined;
+ let smallestDistance = Number.MAX_SAFE_INTEGER;
+ for (let prob of probList)
+ {
+ const delta = Math.abs(prob.id - problem.id);
+ if (delta < smallestDistance &&
+ ((direction == "backward" && prob.id < problem.id)
+ || (direction == "forward" && prob.id > problem.id)))
+ {
+ neighbor = prob;
+ smallestDistance = delta;
+ }
+ }
+ return neighbor;