diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..cb83045
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/supabase/functions/.env b/supabase/functions/.env
new file mode 100644
index 0000000..db53efa
--- /dev/null
+++ b/supabase/functions/.env
@@ -0,0 +1 @@
+JUDGE0_ENDPOINT=http://192.168.50.83:2358
\ No newline at end of file
diff --git a/supabase/functions/fresh-challenges/index.ts b/supabase/functions/fresh-challenges/index.ts
new file mode 100644
index 0000000..f9ef8b1
--- /dev/null
+++ b/supabase/functions/fresh-challenges/index.ts
@@ -0,0 +1,44 @@
+import { createClient } from "https://esm.sh/@supabase/supabase-js";
+
+// http://127.0.0.1:54321/functions/v1/fresh-challenges
+// Auto get judging status from remote lawyers
+
+Deno.serve(async (req) => {
+ try {
+ const client = createClient(
+ Deno.env.get("SUPABASE_URL") ?? "",
+ Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
+ );
+
+ const body = await req.json();
+
+ const { data } = await client
+ .from("challenges")
+ .select("*")
+ .eq("status", "judging")
+ .eq("id", body.id)
+ .single();
+
+ if (data == null || data?.details?.submissions == null) {
+ return new Response(String("Unable to find the challenge with the id in the request."), { status: 400 });
+ }
+
+ const tokens = data?.details?.submissions
+ .map((item: { token: string }) => item.token)
+ .join(",");
+
+ const resp = await fetch(
+ Deno.env.get("JUDGE0_ENDPOINT") + `/submissions/batch?tokens=${tokens}`,
+ { method: "GET" }
+ );
+
+ const result = await resp.json();
+
+ return new Response(JSON.stringify({ result }), {
+ headers: { "Content-Type": "application/json" },
+ status: 200
+ });
+ } catch (err) {
+ return new Response(String(err?.message ?? err), { status: 500 });
+ }
+});
\ No newline at end of file
diff --git a/supabase/functions/judge-challenges/index.ts b/supabase/functions/judge-challenges/index.ts
index f1b224e..dd13803 100644
--- a/supabase/functions/judge-challenges/index.ts
+++ b/supabase/functions/judge-challenges/index.ts
@@ -1,39 +1,58 @@
import { createClient } from "https://esm.sh/@supabase/supabase-js";
+import { runChallenge } from "./runners/index.ts";
-Deno.serve(async (req) => {
+// http://127.0.0.1:54321/functions/v1/judge-challenges
+// Judge all status is submitted challenges
+
+Deno.serve(async (_) => {
try {
const client = createClient(
- Deno.env.get('SUPABASE_URL') ?? '',
- Deno.env.get('SUPABASE_ANON_KEY') ?? '',
- { global: { headers: { Authorization: req.headers.get('Authorization')! } } }
- )
+ Deno.env.get("SUPABASE_URL") ?? "",
+ Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
+ );
const { data, error } = await client
- .from('challenges')
- .select('*')
- .eq('status', 'submitted')
+ .from("challenges")
+ .select("*")
+ .eq("status", "submitted")
+ .limit(20);
if (error) {
- throw error
+ throw error;
}
- return new Response(JSON.stringify({ data }), {
- headers: { 'Content-Type': 'application/json' },
- status: 200,
- })
+ let counter = 0;
+ for (const item of data) {
+ const { data: problem } = await client
+ .from("problems")
+ .select("*")
+ .eq("id", item.problem)
+ .single();
+
+ if (problem == null) {
+ throw new Error("Problem was not found.");
+ }
+
+ const { data: cases } = await client
+ .from("problem_cases")
+ .select("*")
+ .eq("problem", problem.id);
+
+ const result = await runChallenge(item, problem, cases);
+
+ await client
+ .from("challenges")
+ .update({ status: result.status === "skipped" ? "finished" : "judging", details: result })
+ .eq("id", item.id);
+
+ counter++;
+ }
+
+ return new Response(JSON.stringify({ judged: counter }), {
+ headers: { "Content-Type": "application/json" },
+ status: 200
+ });
} catch (err) {
- return new Response(String(err?.message ?? err), { status: 500 })
+ return new Response(String(err?.message ?? err), { status: 500 });
}
});
-
-/* To invoke locally:
-
- 1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start)
- 2. Make an HTTP request:
-
- curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/judge-challenges' \
- --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
- --header 'Content-Type: application/json' \
- --data '{"name":"Functions"}'
-
-*/
diff --git a/supabase/functions/judge-challenges/runners/index.ts b/supabase/functions/judge-challenges/runners/index.ts
new file mode 100644
index 0000000..b829904
--- /dev/null
+++ b/supabase/functions/judge-challenges/runners/index.ts
@@ -0,0 +1,10 @@
+import { runProgramChallenge } from "./programming.ts";
+
+export async function runChallenge(challenge: any, problem: any, cases: any) {
+ switch (problem.type) {
+ case "programming":
+ return await runProgramChallenge(challenge, problem, cases)
+ default:
+ throw new Error("Unsupported problem type.")
+ }
+}
\ No newline at end of file
diff --git a/supabase/functions/judge-challenges/runners/programming.ts b/supabase/functions/judge-challenges/runners/programming.ts
new file mode 100644
index 0000000..158e866
--- /dev/null
+++ b/supabase/functions/judge-challenges/runners/programming.ts
@@ -0,0 +1,40 @@
+export async function runProgramChallenge(challenge: any, problem: any, cases: any[]) {
+ const languages: { [id: string]: number } = {
+ "cpp": 54
+ };
+
+ const code = challenge.answers?.code;
+ const language = challenge.answers?.language;
+ if (!code || !language || !cases || Object.keys(languages).indexOf(language) < 0) {
+ return {
+ status: "skipped",
+ submissions: null
+ };
+ }
+
+ const idx = languages[language];
+ const submissions = cases.map((item: any) => {
+ return {
+ "language_id": idx,
+ "source_code": challenge.answers?.code,
+ "expected_output": item?.stdout,
+ "stdin": code
+ };
+ });
+
+ const resp = await fetch(
+ Deno.env.get("JUDGE0_ENDPOINT") + "/submissions/batch",
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ submissions })
+ }
+ );
+
+ const result = await resp.json();
+
+ return {
+ status: "judging",
+ submissions: result
+ };
+}
\ No newline at end of file