Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/challenges-platform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export {
ReviewsService,
SubmissionService,
AccessibleChallengesService,
JudgesService,
} from "./services";
import { Transformer } from "./models";
import { transformers } from "../../config/challenges-platform/transformers";
Expand Down
9 changes: 9 additions & 0 deletions app/challenges-platform/models/Judge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class Judge {
id: number;
uuid: string;

constructor({ id, uuid }: { id: number; uuid: string }) {
this.id = id;
this.uuid = uuid;
}
}
5 changes: 5 additions & 0 deletions app/challenges-platform/models/Submission.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import { Challenge } from "./Challenge";
import { Participant } from "./Participant";
import { Judge } from "./Judge";

export class Submission {
id: number;
uuid: string;
challenge: Challenge;
participant: Participant;
assignee: Judge | null;

constructor({
id,
uuid,
challenge,
participant,
assignee,
}: {
id: number;
uuid: string;
challenge: Challenge;
participant: Participant;
assignee: Judge | null;
}) {
this.id = id;
this.uuid = uuid;
this.challenge = challenge;
this.participant = participant;
this.assignee = assignee;
}
}
2 changes: 2 additions & 0 deletions app/challenges-platform/models/Transformer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Challenge, Evaluation, Format } from "./Challenge";
import { Participant } from "./Participant";
import { Submission } from "./Submission";
import { Judge } from "./Judge";

export abstract class Transformer {
public static newChallenge(payload: any): Challenge {
Expand Down Expand Up @@ -53,6 +54,7 @@ export class BaseTransformer extends Transformer {
uuid: payload.uuid,
challenge: challenge,
participant: participant,
assignee: null,
});
return submission;
}
Expand Down
1 change: 1 addition & 0 deletions app/challenges-platform/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { Participant } from "./Participant";
export { Review, Status } from "./Review";
export { Submission } from "./Submission";
export { Transformer } from "./Transformer";
export { Judge } from "./Judge";
1 change: 1 addition & 0 deletions app/challenges-platform/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * as ChallengesService from "./challenges-service";
export * as ParticipantsService from "./participants-service";
export * as ReviewsService from "./reviews-service";
export * as SubmissionService from "./submissions-service";
export * as JudgesService from "./judges-service";
26 changes: 26 additions & 0 deletions app/challenges-platform/services/judges-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { eq } from "drizzle-orm";
import { Ok, Err, Result } from "ts-results";
import { db } from "../../../db";
import { judges } from "../../../db/schema";
import { uuid } from "../../../app/common";
import { Judge } from "../models";

export const findByUuid = async (id: string): Promise<Result<Judge, Error>> => {
if (!uuid.isValid(id)) {
return Err(new Error("Invalid UUID"));
}

const result = await db.select().from(judges).where(eq(judges.uuid, id));

if (result.length === 0) {
return Err(new Error("Judge not found"));
}

const record = result[0];
const judge = new Judge({
id: record.id,
uuid: record.uuid,
});

return Ok(judge);
};
38 changes: 38 additions & 0 deletions app/challenges-platform/services/submissions-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
AccessibleChallengesService,
ChallengesService,
ParticipantsService,
JudgesService,
} from "../services";
import { challengesPlatform } from "..";

Expand Down Expand Up @@ -135,3 +136,40 @@ const beforeCreate = async (

return Ok([challengeResult.val, participantResult.val]);
};

export const assign = async (
submissionId: string,
judgeId: string,
): Promise<Result<Submission, Error>> => {
const submissionResult = await findByUuid(submissionId);
if (!submissionResult.ok) {
return Err(new Error("Failed to find submission"));
}

const judgeResult = await JudgesService.findByUuid(judgeId);
if (!judgeResult.ok) {
return Err(new Error("Failed to find judge"));
}

const submission = submissionResult.val;

const result = await db
.update(submissions)
.set({ assignee: judgeResult.val.id })
.where(eq(submissions.id, submission.id))
.returning();

if (result.length === 0) {
return Err(new Error("Failed to assign judge"));
}

const updatedSubmission = new Submission({
id: submission.id,
uuid: submission.uuid,
challenge: submission.challenge,
participant: submission.participant,
assignee: judgeResult.val,
});

return Ok(updatedSubmission);
};
6 changes: 5 additions & 1 deletion app/event-management/models/FlagChallenge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Participant,
Submission,
Transformer,
Judge,
} from "../../challenges-platform/models";

export class FlagChallengeSubmission extends Submission {
Expand All @@ -16,14 +17,16 @@ export class FlagChallengeSubmission extends Submission {
challenge,
participant,
flag,
assignee,
}: {
id: number;
uuid: string;
challenge: Challenge;
participant: Participant;
flag: string;
assignee: Judge | null;
}) {
super({ id, uuid, challenge, participant });
super({ id, uuid, challenge, participant, assignee });
this.flag = flag;
}
}
Expand Down Expand Up @@ -90,6 +93,7 @@ export class FlagTransformer extends Transformer {
challenge: challenge,
participant: participant,
flag: payload.flag,
assignee: null,
});
return submission;
}
Expand Down
5 changes: 4 additions & 1 deletion app/event-management/models/GithubIssueChallenge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Participant,
Submission,
Transformer,
Judge,
} from "../../challenges-platform/models";

export class GithubIssueChallengeSubmission extends Submission {
Expand All @@ -18,15 +19,17 @@ export class GithubIssueChallengeSubmission extends Submission {
repositoryId,
challenge,
participant,
assignee,
}: {
id: number;
uuid: string;
issueId: string;
repositoryId: string;
challenge: Challenge;
participant: Participant;
assignee: Judge | null;
}) {
super({ id, uuid, challenge, participant });
super({ id, uuid, challenge, participant, assignee });
this.issueId = issueId;
this.repositoryId = repositoryId;
}
Expand Down
5 changes: 4 additions & 1 deletion app/event-management/models/PhotoChallenge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Participant,
Submission,
Transformer,
Judge,
} from "../../challenges-platform/models";

export class PhotoChallengeSubmission extends Submission {
Expand All @@ -16,14 +17,16 @@ export class PhotoChallengeSubmission extends Submission {
photoUrl,
challenge,
participant,
assignee,
}: {
id: number;
uuid: string;
photoUrl: string;
challenge: Challenge;
participant: Participant;
assignee: Judge | null;
}) {
super({ id, uuid, challenge, participant });
super({ id, uuid, challenge, participant, assignee });
this.photoUrl = photoUrl;
}
}
Expand Down
8 changes: 8 additions & 0 deletions db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const submissions = sqliteTable("submissions", {
metadata: text("metadata", { mode: "json" }),
challengeId: integer("challenge_id").references(() => challenges.id),
participantId: integer("participant_id").references(() => participants.id),
assignee: integer("assignee").references(() => judges.id),
createdAt: text("created_at").default(sql`CURRENT_TIMESTAMP`),
updatedAt: text("updated_at").default(sql`CURRENT_TIMESTAMP`),
});
Expand All @@ -49,3 +50,10 @@ export const reviews = sqliteTable("reviews", {
createdAt: text("created_at").default(sql`CURRENT_TIMESTAMP`),
updatedAt: text("updated_at").default(sql`CURRENT_TIMESTAMP`),
});

export const judges = sqliteTable("judges", {
id: integer("id").primaryKey(),
uuid: text("uuid").notNull(),
createdAt: text("created_at").default(sql`CURRENT_TIMESTAMP`),
updatedAt: text("updated_at").default(sql`CURRENT_TIMESTAMP`),
});
6 changes: 5 additions & 1 deletion test/challenges-platform/custom-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Participant,
Submission,
Transformer,
Judge,
} from "../../app/challenges-platform/models";

export class CustomSubmission extends Submission {
Expand All @@ -18,15 +19,17 @@ export class CustomSubmission extends Submission {
participant,
propString,
propNumber,
assignee,
}: {
id: number;
uuid: string;
challenge: Challenge;
participant: Participant;
propString: string;
propNumber: number;
assignee: Judge | null;
}) {
super({ id, uuid, challenge, participant });
super({ id, uuid, challenge, participant, assignee });
this.propString = propString;
this.propNumber = propNumber;
}
Expand Down Expand Up @@ -103,6 +106,7 @@ export class CustomTransformer extends Transformer {
participant: participant,
propString: payload.propString,
propNumber: payload.propNumber,
assignee: null,
});
return submission;
}
Expand Down
20 changes: 20 additions & 0 deletions test/challenges-platform/factories/judge-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { db } from "../../../db";
import { judges } from "../../../db/schema";
import { uuid } from "../../../app/common";
import { Judge } from "../../../app/challenges-platform/models";

export const judgeFactory = async (): Promise<Judge> => {
const insertResult = await db
.insert(judges)
.values({
uuid: uuid.create(),
})
.returning();

const judge = new Judge({
id: insertResult[0].id,
uuid: insertResult[0].uuid,
});

return judge;
};
36 changes: 36 additions & 0 deletions test/challenges-platform/services/judges-service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { JudgesService } from "../../../app/challenges-platform";
import { judgeFactory } from "../factories/judge-factory";
import { uuid } from "../../../app/common";

describe("JudgesService", () => {
describe("findByUuid", () => {
describe("when the id is invalid", () => {
it("returns an error", async () => {
const result = await JudgesService.findByUuid("invalid-id");

expect(result.err).toBe(true);
expect(result.val.toString()).toBe("Error: Invalid UUID");
});
});

describe("when there is no record", () => {
it("returns an error", async () => {
const testUuid = uuid.create();
const result = await JudgesService.findByUuid(testUuid);

expect(result.err).toBe(true);
expect(result.val.toString()).toBe("Error: Judge not found");
});
});

describe("when there is an existing record", () => {
it("returns the judge", async () => {
const judge = await judgeFactory();
const result = await JudgesService.findByUuid(judge.uuid);

if (!result.ok) fail("Expected result to be Ok");
expect(result.val.uuid).toBe(judge.uuid);
});
});
});
});
Loading