Skip to content

Commit

Permalink
Merge branch 'release' into feature/sprint2
Browse files Browse the repository at this point in the history
  • Loading branch information
Mirrorgo committed Oct 9, 2024
2 parents c57a4c7 + 4e3599d commit e72e831
Show file tree
Hide file tree
Showing 6 changed files with 640 additions and 17 deletions.
131 changes: 125 additions & 6 deletions app/sample/components/sampleSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React from "react";
import Image from "next/image";
import useMultiWinnerDataStore from "../../../store/MultiWinnerData";
import { AvatarColor } from "@/utils/avatarColor";
import { explainAssertions } from "../../explain-assertions/components/explain_process";
import { useRouter } from "next/navigation";

type SampleFile = {
name: string;
Expand All @@ -13,26 +17,141 @@ const sampleFiles: SampleFile[] = [
name: "NEB Assertion",
description: "NEB assertions example",
imageUrl: "/sample-images/img.png",
fileUrl: "/sample-jsons/a_guide_to_RAIRE_eg_NEB_assertions.json",
// fileUrl: "/sample-jsons/a_guide_to_RAIRE_eg_NEB_assertions.json",
fileUrl: "/sample-jsons/City of Coffs Harbour Mayoral.json",
},
{
name: "One candidate dominates example",
description: "One candidate dominates example",
imageUrl: "/sample-images/img.png",
fileUrl: "/sample-jsons/a_guide_to_RAIRE_eg_one_candidate_dominates.json",
// fileUrl: "/sample-jsons/a_guide_to_RAIRE_eg_one_candidate_dominates.json",
fileUrl: "/sample-jsons/Singleton Mayoral.json",
},
{
name: "Two leading candidates example",
description: "Two leading candidates example ",
imageUrl: "/sample-images/img.png",
fileUrl: "/sample-jsons/a_guide_to_RAIRE_eg_two_leading_candidates.json",
// fileUrl: "/sample-jsons/a_guide_to_RAIRE_eg_two_leading_candidates.json",
fileUrl: "/sample-jsons/test.json",
},
];

const SampleSelector = () => {
const handleSampleClick = (fileUrl: string) => {
// Logic to handle sample file selection
console.log("Selected sample:", fileUrl);
const { setMultiWinner, setCandidateList, setAssertionList } =
useMultiWinnerDataStore(); // 使用全局状态
const avatarColor = new AvatarColor();
const router = useRouter();

const handleSampleClick = async (fileUrl: string) => {
try {
// 使用 fetch 获取样例文件
const response = await fetch(fileUrl);
if (!response.ok) {
throw new Error("Failed to fetch the sample file");
}

// 将样例文件转换为 Blob 对象
const blob = await response.blob();
const reader = new FileReader();

// 使用 FileReader 读取 Blob 的内容
reader.onload = (e) => {
const result = e.target?.result;

if (typeof result === "string") {
// 解析文件内容并调用核心库进行校验和解析
const response = explainAssertions(result);
console.log("response", response);
if (response.success) {
// 成功解析,将数据存储到全局状态中
setMultiWinner(response.data);
const jsonData = JSON.parse(result);

// 处理候选人列表
const candidateList = jsonData.metadata.candidates.map(
(name: string, index: number) => ({
id: index,
name: name,
color: avatarColor.getColor(index),
}),
);
console.log("candidateList", candidateList);
setCandidateList(candidateList);

// 将候选人列表转换为字典,便于后续查找
const candidateMap = candidateList.reduce(
(
acc: { [key: number]: string },
candidate: { id: number; name: string; color: string },
) => {
acc[candidate.id] = candidate.name;
return acc;
},
{} as { [key: number]: string },
);

// 提取 assertions 并生成 assertionList
const assertions = jsonData.solution.Ok.assertions;
const assertionList = assertions.map(
(
assertionObj: {
assertion: {
type: string;
winner: number;
loser: number;
continuing: number[];
};
difficulty: number;
margin: number;
},
index: number,
) => {
const { assertion, difficulty, margin } = assertionObj;
const { type, winner, loser, continuing } = assertion;

// 获取 winner 和 loser 的名字
const winnerName = candidateMap[winner];
const loserName = candidateMap[loser];

// 根据不同类型生成 content 字段
let content = "";
if (type === "NEN") {
const continuingNames = continuing
.map((id) => candidateMap[id])
.join(", ");
content = `${winnerName} > ${loserName} if only {${continuingNames}} remain`;
} else if (type === "NEB") {
content = `${winnerName} NEB ${loserName}`;
}

// 返回 assertionList 的每一项
return {
index: index + 1, // index 从 1 开始
winner: winnerName, // 将 winner 转化为名字
content, // 生成的内容
type, // 保持 type 不变
difficulty, // 保持 difficulty 不变
margin, // 保持 margin 不变
};
},
);
console.log("assertionList", assertionList);
setAssertionList(assertionList);
console.log(
"Successfully processed and stored the sample file data",
);
router.push("/dashboard");
} else {
console.error("Failed to explain assertions", response.error);
}
}
};

// 读取 Blob 内容为文本
reader.readAsText(blob);
} catch (error) {
console.error("Error fetching or processing the sample file:", error);
}
};

return (
Expand Down
23 changes: 18 additions & 5 deletions app/upload/components/uploader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback } from "react";
import { CloudUpload, File, ArrowLeft } from "lucide-react";
import { CloudUpload, File, ArrowLeft, Link } from "lucide-react";
import CustomAlertDialog from "./alertDialog";
import UploadProgress from "./progress";
import useMultiWinnerDataStore from "../../../store/MultiWinnerData";
Expand Down Expand Up @@ -288,6 +288,10 @@ const Uploader: React.FC<UploaderProps> = ({ className }) => {
}
};

const handleBrowseClick = () => {
document.getElementById("file-input")?.click(); // 触发文件上传的点击事件
};

const handleReset = () => {
setSelectedFile(null); // 清空选中的文件
clearMultiWinner(); // 清空全局状态中的 JSON 数据
Expand Down Expand Up @@ -365,19 +369,28 @@ const Uploader: React.FC<UploaderProps> = ({ className }) => {
{/* 设置 CloudUpload 图标大小 */}
<p className="text-gray-600">
Drag or{" "}
<span className="text-blue-600 cursor-pointer">Browse</span>{" "}
<span
className="text-blue-600 cursor-pointer hover:underline"
onClick={handleBrowseClick}
>
Browse
</span>{" "}
your files
</p>
<p className="text-gray-400 mb-2">or</p>
{/* Sample文件 TODO */}
<a href="#" className="text-blue-600">
<button
onClick={() => router.push("/sample")} // 跳转到Sample页面
className="text-blue-600 hover:underline"
>
Use a sample file
</a>
</button>
<input
id="file-input"
type="file"
accept="application/json, text/plain"
onChange={handleFileChange}
className="top-0 left-0 w-full h-full opacity-0 cursor-pointer absolute"
style={{ display: "none" }} // 隐藏上传文件的输入框
/>
<p className="text-sm text-gray-400 mt-4 absolute bottom-2 left-2">
Supported files: .json, .txt | Upload limit: 100MB
Expand Down
16 changes: 10 additions & 6 deletions app/upload/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
import Image from "next/image";
import Uploader from "./components/uploader";
import React, { useEffect } from "react";
import { useRouter } from "next/navigation";

const Dashboard: React.FC = () => {
const router = useRouter();
const jumpToTutorial = () => {
router.push("/tutorial");
};
useEffect(() => {
const fetchData = async () => {
try {
Expand All @@ -20,10 +25,6 @@ const Dashboard: React.FC = () => {
return (
<div className="flex flex-col h-screen">
<main className="flex flex-col bg-gray-100 p-8 h-screen">
<div className="flex items-center mb-6">
<Image src="/Logo.png" alt="Logo" width={80} height={80} />
<h1 className="text-3xl font-bold">AuditVisualiser</h1>
</div>
<div className="bg-white shadow-md rounded-lg p-6 flex flex-col flex-grow">
<h2 className="text-3xl font-bold text-left">
Show the effect of assertions
Expand All @@ -46,9 +47,12 @@ const Dashboard: React.FC = () => {
</div>
<div className="text-center text-lg text-gray-600 my-4">
Need help? Click{" "}
<a href="#" className="text-blue-600 hover:underline">
<span
onClick={jumpToTutorial}
className="text-blue-600 hover:underline"
>
here
</a>{" "}
</span>{" "}
for a tutorial.
</div>
</main>
Expand Down
Loading

0 comments on commit e72e831

Please sign in to comment.