Skip to content

Commit

Permalink
Merge pull request #276 from bettersg/bug/handle-unsure-and-error-pro…
Browse files Browse the repository at this point in the history
…perly

Bug/handle unsure and error properly
  • Loading branch information
sarge1989 authored Apr 8, 2024
2 parents bd44286 + 040d7cb commit 9d5f157
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 191 deletions.
8 changes: 5 additions & 3 deletions checkers-app/src/components/dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function Dashboard() {
const [isLoading, setIsLoading] = useState(false);
const { checkerId, pendingCount, setPendingCount } = useUser();
const [totalVotes, setTotalVotes] = useState<number>(0);
const [accuracyRate, setAccuracyRate] = useState<number>(0);
const [accuracyRate, setAccuracyRate] = useState<number | null>(0);
const [avgResponseTime, setAvgResponseTime] = useState<number>(0);
const [peopleHelped, setPeopleHelped] = useState<number>(0);

Expand Down Expand Up @@ -61,12 +61,14 @@ export default function Dashboard() {
<StatCard
name="average accuracy rate"
img_src="/accuracy.png"
stat={`${(accuracyRate * 100).toFixed(2)}%`}
stat={
accuracyRate === null ? "NA" : `${(accuracyRate * 100).toFixed(1)}%`
}
/>
<StatCard
name="average response time"
img_src="/response.png"
stat={`${avgResponseTime.toFixed(2)} mins`}
stat={`${avgResponseTime.toFixed(0)} mins`}
/>
<StatCard
name="people helped"
Expand Down
81 changes: 46 additions & 35 deletions checkers-app/src/components/myvotes/MessageCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VoteSummary } from "../../types";
import { useNavigate } from "react-router-dom";
import { PencilIcon } from "@heroicons/react/20/solid";
import { PencilIcon, QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
import "./MessageCard.css";

interface MessageCardProps {
Expand All @@ -21,23 +21,6 @@ const colours: ColourMap = {
WAITING: "waiting-color",
};

// function getCategory(msg: Message): string {
// if (msg.voteRequests.category == null) {
// return "PENDING";
// }
// else if (!msg.isAssessed && msg.voteRequests.category != null) {
// return "WAITING";
// }
// else {
// if (msg.isMatch) {
// return "CORRECT"
// }
// else {
// return "INCORRECT"
// }
// }
// }

function dateToDateString(date: Date | null): string {
// Parse the ISO string into a Date object
if (date === null) {
Expand Down Expand Up @@ -84,6 +67,7 @@ export default function MessageCard(props: MessageCardProps) {
//caption,
needsReview,
isAssessed,
isUnsure,
firestorePath,
} = props.voteSummary;
const status = props.status;
Expand All @@ -98,30 +82,57 @@ export default function MessageCard(props: MessageCardProps) {

const textStyle = "font-normal"; //add bold in future

function renderStatusDot() {
// Checking if the status is 'voted'
if (status === "voted") {
if (isAssessed) {
if (isUnsure) {
// Is unsure
return (
<div className="w-1/12 flex items-center justify-center">
<QuestionMarkCircleIcon className="h-4 w-4" />
</div>
);
} else {
if (needsReview) {
return (
<div className="w-1/12 flex items-center justify-center">
<div
className={`w-4 h-4 rounded-full bg-${colours.INCORRECT}`}
></div>
</div>
);
} else {
return (
<div className="w-1/12 flex items-center justify-center">
<div
className={`w-4 h-4 rounded-full bg-${colours.CORRECT}`}
></div>
</div>
);
}
}
} else {
// Not assessed
return (
<div className="w-1/12 flex items-center justify-center">
<PencilIcon className="h-4 w-4" />
</div>
);
}
}
// If none of the conditions match, return null
return null;
}

return (
<div
className="flex border-b border-gray-500 h-16 hover-shadow dark:bg-dark-background-color"
onClick={() => viewVote(firestorePath)}
>
{/* Coloured dot if needs review*/}

{isAssessed && needsReview && status === "voted" && (
<div className="w-1/12 flex items-center justify-center">
<div className={`w-4 h-4 rounded-full bg-${colours.INCORRECT}`}></div>
</div>
)}

{isAssessed && !needsReview && status === "voted" && (
<div className="w-1/12 flex items-center justify-center">
<div className={`w-4 h-4 rounded-full bg-${colours.CORRECT}`}></div>
</div>
)}

{!isAssessed && status === "voted" && (
<div className="w-1/12 flex items-center justify-center">
<PencilIcon className="h-4 w-4" />
</div>
)}
{renderStatusDot()}

{/* Message content */}
<div className="w-11/12 p-2">
Expand Down
8 changes: 5 additions & 3 deletions functions/src/definitions/api/handlers/getChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ const getCheckerHandler = async (req: Request, res: Response) => {
const accurateCount = results.filter(
(d) => d !== null && d.isAccurate
).length
const totalAssessedCount = results.filter(
(d) => d !== null && d.isAssessed
const totalAssessedAndNonUnsureCount = results.filter(
(d) => d !== null && d.isAssessed && d.isAccurate !== null
).length
const totalCount = results.filter((d) => d !== null).length
//calculate people helped
Expand All @@ -126,7 +126,9 @@ const getCheckerHandler = async (req: Request, res: Response) => {
const averageResponseTime = totalResponseTime / (totalCount || 1)

const accuracyRate =
totalAssessedCount === 0 ? 1 : accurateCount / totalAssessedCount
totalAssessedAndNonUnsureCount === 0
? null
: accurateCount / totalAssessedAndNonUnsureCount
const returnData: Checker = {
name: checkerData.name,
type: checkerData.type,
Expand Down
6 changes: 4 additions & 2 deletions functions/src/definitions/api/handlers/getCheckerVotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ const getCheckerVotesHandler = async (req: Request, res: Response) => {
const caption = latestInstanceSnap.get("caption") ?? null
const isAssessed = parentMessageSnap.get("isAssessed") ?? false
const firestorePath = doc.ref.path
const needsReview =
isAssessed && checkAccuracy(parentMessageSnap, doc) === false
const isCorrect = checkAccuracy(parentMessageSnap, doc)
const needsReview = isAssessed && isCorrect === false
const isUnsure = isCorrect === null //either unsure or some other type of error

const returnObject: VoteSummary = {
category,
Expand All @@ -110,6 +111,7 @@ const getCheckerVotesHandler = async (req: Request, res: Response) => {
caption,
needsReview,
isAssessed,
isUnsure,
firestorePath,
}
return returnObject
Expand Down
8 changes: 8 additions & 0 deletions functions/src/definitions/api/handlers/getVote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ const getVoteHandler = async (req: Request, res: Response) => {

const latestType = latestInstanceSnap.get("type") ?? "text"

const sender = latestInstanceSnap.get("from") ?? "Unknown"

//mask all but last 4 characters of sender

const maskedSender =
sender != "Unknown" ? sender.replace(/.(?=.{4})/g, "*") : sender

const storageBucketUrl = latestInstanceSnap.get("storageUrl")
const signedUrl =
latestType === "image" ? await getSignedUrl(storageBucketUrl) : null
Expand Down Expand Up @@ -123,6 +130,7 @@ const getVoteHandler = async (req: Request, res: Response) => {
latestType === "image" ? latestInstanceSnap.get("caption") : null,
signedImageUrl: signedUrl,
category: voteRequestSnap.get("category"),
sender: maskedSender,
truthScore: isLegacy
? voteRequestSnap.get("vote")
: voteRequestSnap.get("truthScore"),
Expand Down
4 changes: 3 additions & 1 deletion functions/src/definitions/api/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ interface VoteSummary {
caption: string | null //only for type image
needsReview: boolean //if the vote differs from the majority
isAssessed: boolean //if the message is assessed
isUnsure: boolean //if the final assessed category ended as unsure
firestorePath: string
}

Expand All @@ -76,6 +77,7 @@ interface VoteSummaryApiResponse {
interface Vote {
type: "image" | "text"
text: string | null //only for type text
sender: string
caption: string | null //only for type image
signedImageUrl: string | null //only for type image
category: string | null
Expand All @@ -86,7 +88,7 @@ interface Vote {

interface last30DaysStats {
totalVoted: number
accuracyRate: number
accuracyRate: number | null
averageResponseTime: number
peopleHelped: number
}
Expand Down
56 changes: 55 additions & 1 deletion functions/src/definitions/common/counters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,58 @@ const getCount = async function (docRef: DocumentReference, type: string) {
return count
}

export { getCount, incrementCounter }
const getVoteCounts = async function (messageRef: DocumentReference) {
const totalVoteRequestQuery = messageRef
.collection("voteRequests")
.count()
.get()
const [
responsesCount,
errorCount,
irrelevantCount,
scamCount,
illicitCount,
infoCount,
spamCount,
legitimateCount,
unsureCount,
satireCount,
voteTotal,
voteRequestCountSnapshot,
] = await Promise.all([
getCount(messageRef, "responses"),
getCount(messageRef, "error"),
getCount(messageRef, "irrelevant"),
getCount(messageRef, "scam"),
getCount(messageRef, "illicit"),
getCount(messageRef, "info"),
getCount(messageRef, "spam"),
getCount(messageRef, "legitimate"),
getCount(messageRef, "unsure"),
getCount(messageRef, "satire"),
getCount(messageRef, "totalVoteScore"),
totalVoteRequestQuery,
])
const totalVoteRequestsCount = voteRequestCountSnapshot.data().count ?? 0
const factCheckerCount = totalVoteRequestsCount - errorCount //don't count "error" votes in number of fact checkers, as this will slow the replies unnecessarily.
const validResponsesCount = responsesCount - errorCount //can remove in future and replace with nonErrorCount
const susCount = scamCount + illicitCount
return {
responsesCount,
errorCount,
irrelevantCount,
scamCount,
illicitCount,
infoCount,
spamCount,
legitimateCount,
unsureCount,
satireCount,
voteTotal,
validResponsesCount,
susCount,
factCheckerCount,
}
}

export { getCount, incrementCounter, getVoteCounts }
Loading

0 comments on commit 9d5f157

Please sign in to comment.