Skip to content

Commit

Permalink
CLDR-15850 Add vote type column to Vetting Participation sheet (#2804)
Browse files Browse the repository at this point in the history
-For now, counts for vote types are shown in the last column

-Change API from dashboard/for, to participation/for

-Omit (unused, large) notifications from Vetting Participation json; new ParticipationResults
  • Loading branch information
btangmu authored Mar 28, 2023
1 parent c05487b commit 07c7ab7
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 70 deletions.
22 changes: 20 additions & 2 deletions tools/cldr-apps/js/src/esm/cldrVettingParticipation.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ async function downloadVettingParticipation(opts) {
"Email",
"Name",
"LastSeen",
"Votes by Type",
],
];

Expand All @@ -150,6 +151,7 @@ async function downloadVettingParticipation(opts) {
user.email,
user.name,
user.time,
"", // typeCount
];
if (user.allLocales) {
row[1] = "ALL";
Expand All @@ -175,10 +177,11 @@ async function downloadVettingParticipation(opts) {
const level = "org";
setStatus(`Fetch ${id}/${locale}/${level}`);
const data = await cldrAjax.doFetch(
`./api/summary/dashboard/for/${id}/${locale}/${level}`
`./api/summary/participation/for/${id}/${locale}/${level}`
);
const json = await data.json();
const { votablePathCount, votedPathCount } = json.voterProgress;
const { votablePathCount, votedPathCount, typeCount } =
json.voterProgress;
const { coverageLevel } = json;
row[6] = votedPathCount;
row[7] = votablePathCount;
Expand All @@ -188,6 +191,7 @@ async function downloadVettingParticipation(opts) {
);
row[8] = `${perCent}%`;
row[9] = (coverageLevel || "").toLowerCase();
row[14] = typeCountToString(typeCount);
} else {
// only guest and vetter users
row[6] = "-";
Expand Down Expand Up @@ -237,6 +241,7 @@ async function downloadVettingParticipation(opts) {
cldrXlsx.pushComment(ws, "L1", "Users' email");
cldrXlsx.pushComment(ws, "M1", "Users' name");
cldrXlsx.pushComment(ws, "N1", "When the user last logged in");
cldrXlsx.pushComment(ws, "O1", "Vote counts by type");

XLSX.utils.book_append_sheet(wb, ws, ws_name);
XLSX.writeFile(
Expand Down Expand Up @@ -517,4 +522,17 @@ function mySort(a, b) {
return a.user.name.localeCompare(b.user.name);
}

function typeCountToString(typeCount) {
let str = "";
if (typeCount) {
for (let key of Object.keys(typeCount).sort()) {
if (str) {
str += ";";
}
str += key + ":" + typeCount[key];
}
}
return str;
}

export { load };
17 changes: 2 additions & 15 deletions tools/cldr-apps/src/main/java/org/unicode/cldr/web/BallotBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,6 @@ public VoteNotAcceptedException(ErrorCode r, String string, JSONObject err_data)
}
}

/**
* Record a vote for an item. Will (eventually) throw a number of
* exceptions.
*
* @param user
* voter's object
* @param distinguishingXpath
* dpath of item
* @param value
* new string value to vote for, or null for "unvote"
* @throws InvalidXPathException
* @throws VoteNotAcceptedException
*/
public void voteForValue(T user, String distinguishingXpath, String value, Integer withVote) throws InvalidXPathException, VoteNotAcceptedException;

public void voteForValue(T user, String distinguishingXpath, String value) throws InvalidXPathException, VoteNotAcceptedException;

public void voteForValueWithType(T user, String distinguishingXpath, String value, VoteType voteType) throws VoteNotAcceptedException, InvalidXPathException;
Expand Down Expand Up @@ -135,6 +120,8 @@ public void voteForValueWithType(T user, String distinguishingXpath, String valu
*/
public boolean userDidVote(User myUser, String somePath);

public VoteType getUserVoteType(User myUser, String somePath);

/**
* Were there any votes some-time this release?
*
Expand Down
12 changes: 2 additions & 10 deletions tools/cldr-apps/src/main/java/org/unicode/cldr/web/Dashboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,11 @@

import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.unicode.cldr.test.CheckCLDR;
import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRLocale;
import org.unicode.cldr.util.Level;
import org.unicode.cldr.util.Organization;
import org.unicode.cldr.util.*;
import org.unicode.cldr.util.PathHeader.PageId;
import org.unicode.cldr.util.PathHeader.SectionId;
import org.unicode.cldr.util.VettingViewer;
import org.unicode.cldr.util.NotificationCategory;
import org.unicode.cldr.util.VettingParameters;
import org.unicode.cldr.util.VoterReportStatus.ReportId;
import org.unicode.cldr.util.VoterReportStatus.ReportStatus;
import org.unicode.cldr.util.VoterProgress;
import org.unicode.cldr.util.VoterReportStatus;

import com.ibm.icu.impl.Relation;
import com.ibm.icu.impl.Row;
Expand Down Expand Up @@ -105,7 +97,7 @@ public void addReports(int userId, String localeId) {
}
// update counts. Completed are both voted and votable.
reportStatus.completed.forEach(r -> {
voterProgress.incrementVotedPathCount();
voterProgress.incrementVotedPathCount(VoteType.DIRECT);
voterProgress.incrementVotablePathCount();
});
// Incomplete are votable but not voted.
Expand Down
73 changes: 57 additions & 16 deletions tools/cldr-apps/src/main/java/org/unicode/cldr/web/STFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -407,10 +407,17 @@ private final class PerUserData {
Integer override;
Date when;

public PerUserData(String value, Integer voteOverride, Date when) {
VoteType voteType;

public PerUserData(String value, Integer voteOverride, Date when, VoteType voteType) {
this.vote = value;
this.override = voteOverride;
this.when = when;
this.voteType = voteType;
if (voteType == null || voteType == VoteType.NONE) {
logger.warning("PerUserData got vote type " + voteType + "; changed to UNKNOWN");
voteType = VoteType.UNKNOWN;
}
if (lastModDate == null || lastModDate.before(when)) {
lastModDate = when;
}
Expand All @@ -431,6 +438,10 @@ public String getValue() {
public Date getWhen() {
return when;
}

public VoteType getVoteType() {
return voteType;
}
}

Date lastModDate = null;
Expand Down Expand Up @@ -491,9 +502,9 @@ private PerUserData peekUserToData(User user) {
return userToData.get(user);
}

private void setVoteForValue(User user, String value, Integer voteOverride, Date when) {
private void setVoteForValue(User user, String value, Integer voteOverride, Date when, VoteType voteType) {
if (value != null) {
setPerUserData(user, new PerUserData(value, voteOverride, when));
setPerUserData(user, new PerUserData(value, voteOverride, when, voteType));
} else {
removePerUserData(user);
}
Expand Down Expand Up @@ -554,6 +565,17 @@ public boolean userDidVote(User myUser) {
return (pud != null && pud.getValue() != null);
}

public VoteType getUserVoteType(User myUser) {
if (userToData == null) {
return VoteType.NONE;
}
PerUserData pud = peekUserToData(myUser);
if (pud == null) {
return VoteType.NONE;
}
return pud.getVoteType();
}

public Map<User, Integer> getOverridesPerUser() {
if (isEmpty()) return null;
Map<User, Integer> rv = new HashMap<>(userToData.size());
Expand Down Expand Up @@ -651,7 +673,7 @@ private void loadVoteValues(DataBackedSource targetXmlSource, VoteLoadingContext

try {
/*
* Select several columns (xp, submitter, value, override, last_mod),
* Select several columns (xp, submitter, value, override, last_mod, vote_type),
* from all rows with the given locale in the votes table.
*/
conn = DBUtils.getInstance().getAConnection();
Expand All @@ -673,6 +695,7 @@ private void loadVoteValues(DataBackedSource targetXmlSource, VoteLoadingContext
voteOverride = null;
}
Timestamp last_mod = rs.getTimestamp(6); // last mod
VoteType voteType = VoteType.fromId(rs.getInt(7)); // vote_type
User theSubmitter = sm.reg.getInfo(submitter);
if (theSubmitter == null) {
SurveyLog.warnOnce(logger, "Ignoring votes for deleted user #" + submitter);
Expand All @@ -685,7 +708,11 @@ private void loadVoteValues(DataBackedSource targetXmlSource, VoteLoadingContext
}
try {
value = processValue(xpath, value);
internalSetVoteForValue(theSubmitter, xpath, value, voteOverride, last_mod);
if (voteType == null || voteType == VoteType.NONE) {
logger.warning("loadVoteValues got vote type " + voteType + "; changed to UNKNOWN");
voteType = VoteType.UNKNOWN;
}
internalSetVoteForValue(theSubmitter, xpath, value, voteOverride, last_mod, voteType);
n++;
} catch (VoteNotAcceptedException e) {
logger.severe("VoteNotAcceptedException: " + theSubmitter + ":" + locale + ":" + xpath);
Expand All @@ -708,7 +735,7 @@ private void loadVoteValues(DataBackedSource targetXmlSource, VoteLoadingContext
String value = DBUtils.getStringUTF8(rs, 2);
Timestamp last_mod = rs.getTimestamp(3);
try {
internalSetVoteForValue(sm.reg.getInfo(UserRegistry.ADMIN_ID), xpath, value, VoteResolver.Level.LOCKING_VOTES, last_mod);
internalSetVoteForValue(sm.reg.getInfo(UserRegistry.ADMIN_ID), xpath, value, VoteResolver.Level.LOCKING_VOTES, last_mod, VoteType.DIRECT);
n++;
} catch (BallotBox.InvalidXPathException e) {
System.err.println("InvalidXPathException: Ignoring permanent vote for:" + locale + ":" + xpath);
Expand Down Expand Up @@ -995,11 +1022,6 @@ public void revoteFor(User user, String distinguishingXpath) throws BallotBox.In
voteForValue(user, distinguishingXpath, oldValue);
}

@Override
public void voteForValue(User user, String distinguishingXpath, String value, Integer withVote) throws InvalidXPathException, VoteNotAcceptedException {
voteForValueWithType(user, distinguishingXpath, value, withVote, VoteType.DIRECT);
}

@Override
public void voteForValue(User user, String distinguishingXpath, String value) throws InvalidXPathException, VoteNotAcceptedException {
voteForValueWithType(user, distinguishingXpath, value, null, VoteType.DIRECT);
Expand Down Expand Up @@ -1057,7 +1079,7 @@ public synchronized void voteForValueWithType(User user, String distinguishingXp
readonly();
}

internalSetVoteForValue(user, distinguishingXpath, value, withVote, new Date());
internalSetVoteForValue(user, distinguishingXpath, value, withVote, new Date(), voteType);

if (withVote != null && withVote == VoteResolver.Level.PERMANENT_VOTES) {
doPermanentVote(distinguishingXpath, xpathId, value);
Expand Down Expand Up @@ -1219,7 +1241,7 @@ private void doPermanentVote(String distinguishingXpath, int xpathId, String val
if (pv.didLock()) {
User admin = sm.reg.getInfo(UserRegistry.ADMIN_ID);
peekXpathData(distinguishingXpath).setVoteForValue(admin,
value, VoteResolver.Level.LOCKING_VOTES, new Date());
value, VoteResolver.Level.LOCKING_VOTES, new Date(), VoteType.DIRECT);
} else if (pv.didUnlock()) {
peekXpathData(distinguishingXpath).removeOverrideVotes(VoteResolver.Level.LOCKING_VOTES);
}
Expand All @@ -1237,9 +1259,13 @@ private void doPermanentVote(String distinguishingXpath, int xpathId, String val
* Called by loadVoteValues and voteForValue.
*/
private void internalSetVoteForValue(User user, String distinguishingXpath, String value,
Integer voteOverride, Date when) throws InvalidXPathException {
Integer voteOverride, Date when, VoteType voteType) throws InvalidXPathException {
if (voteType == null || voteType == VoteType.NONE) {
logger.warning("internalSetVoteForValue got vote type " + voteType + "; changed to UNKNOWN");
voteType = VoteType.UNKNOWN;
}
makeSureInPathsForFile(distinguishingXpath, user, value);
getXPathData(distinguishingXpath).setVoteForValue(user, value, voteOverride, when);
getXPathData(distinguishingXpath).setVoteForValue(user, value, voteOverride, when, voteType);
stamp.next();
}

Expand All @@ -1249,6 +1275,20 @@ public boolean userDidVote(User myUser, String somePath) {
return (xpd != null && xpd.userDidVote(myUser));
}

@Override
public VoteType getUserVoteType(User myUser, String somePath) {
PerXPathData xpd = peekXpathData(somePath);
if (xpd == null) {
logger.warning("getUserVoteType got xpd null, returning NONE");
return VoteType.NONE;
}
VoteType voteType = xpd.getUserVoteType(myUser);
if (voteType == null || voteType == VoteType.NONE) {
logger.warning("getUserVoteType got vote type " + voteType + "; changed to UNKNOWN");
voteType = VoteType.UNKNOWN;
}
return voteType;
}
public TestResultBundle getTestResultData(CheckCLDR.Options options) {
synchronized (gTestCache) {
return gTestCache.getBundle(options);
Expand Down Expand Up @@ -1715,7 +1755,8 @@ private PreparedStatement openQueryByLocaleRW(Connection conn) throws SQLExcepti
* "must select all primary keys from that table".
*/
return DBUtils
.prepareForwardUpdateable(conn, "SELECT xpath,submitter,value,locale," + VOTE_OVERRIDE + ",last_mod FROM " + DBUtils.Table.VOTE_VALUE
.prepareForwardUpdateable(conn, "SELECT xpath,submitter,value,locale," + VOTE_OVERRIDE + ",last_mod, "
+ VOTE_TYPE + " FROM " + DBUtils.Table.VOTE_VALUE
+ " WHERE locale = ?");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package org.unicode.cldr.web;

import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRLocale;
import org.unicode.cldr.util.LruMap;
import org.unicode.cldr.util.Organization;
import org.unicode.cldr.util.*;
import org.unicode.cldr.util.VettingViewer.UsersChoice;
import org.unicode.cldr.util.VettingViewer.VoteStatus;
import org.unicode.cldr.util.VoteResolver;
import org.unicode.cldr.web.UserRegistry.User;

public class STUsersChoice implements UsersChoice<Organization> {
Expand Down Expand Up @@ -42,6 +38,12 @@ public boolean userDidVote(int userId, CLDRLocale loc, String path) {
return ballotBox.userDidVote(sm.reg.getInfo(userId), path);
}

@Override
public VoteType getUserVoteType(int userId, CLDRLocale loc, String path) {
BallotBox<User> ballotBox = getBox(sm, loc);
return ballotBox.getUserVoteType(sm.reg.getInfo(userId), path);
}

private LruMap<CLDRLocale, BallotBox<UserRegistry.User>> ballotBoxes = new LruMap<>(8);

private BallotBox<UserRegistry.User> getBox(SurveyMain sm, CLDRLocale loc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2367,7 +2367,7 @@ public List<CheckCLDR.CheckStatus> getCheckStatusList() {
resultIcon = "stop";
} else {
if (doFinal) {
ballotBox.voteForValue(u, base, val0);
ballotBox.voteForValueWithType(u, base, val0, VoteType.BULK_UPLOAD);
result = "Vote accepted";
resultIcon = "vote";
} else {
Expand Down
Loading

0 comments on commit 07c7ab7

Please sign in to comment.