|
@@ -15,7 +15,10 @@ import { DrawTrackItem } from '../../../../electron/preload/types';
|
|
|
import { TrackTaskData } from '../../../../electron/db/models/trackTask';
|
|
|
import { TrackTaskDetailData } from '../../../../electron/db/models/trackTaskDetail';
|
|
|
|
|
|
-type AnswerMap = Record<string, { answer: string; isRight: boolean }>;
|
|
|
+type AnswerMap = Record<
|
|
|
+ string,
|
|
|
+ { answer: string; isRight: boolean; score: number; totalScore: number }
|
|
|
+>;
|
|
|
|
|
|
interface TrackItemType {
|
|
|
url: string;
|
|
@@ -31,6 +34,16 @@ type ElementType =
|
|
|
| 'COMPOSITION'
|
|
|
| 'TOPIC_HEAD'
|
|
|
| 'CARD_HEAD';
|
|
|
+interface CardBaseElement {
|
|
|
+ id: string;
|
|
|
+ type: ElementType;
|
|
|
+ topicNo: number;
|
|
|
+ startNumber: number;
|
|
|
+ questionsCount: number;
|
|
|
+}
|
|
|
+interface CardElement extends CardBaseElement {
|
|
|
+ parent: CardBaseElement;
|
|
|
+}
|
|
|
interface CardDataItem {
|
|
|
exchange: {
|
|
|
answer_area: Array<{
|
|
@@ -38,14 +51,20 @@ interface CardDataItem {
|
|
|
sub_number: number | string;
|
|
|
area: [number, number, number, number];
|
|
|
}>;
|
|
|
+ fill_area: Array<{
|
|
|
+ field: 'question' | 'examNumber';
|
|
|
+ index: number;
|
|
|
+ single: boolean;
|
|
|
+ horizontal: boolean;
|
|
|
+ items: Array<{
|
|
|
+ main_number: number;
|
|
|
+ sub_number: number | string;
|
|
|
+ options: [number, number, number, number][];
|
|
|
+ }>;
|
|
|
+ }>;
|
|
|
};
|
|
|
columns: Array<{
|
|
|
- elements: Array<{
|
|
|
- type: ElementType;
|
|
|
- topicNo: number;
|
|
|
- startNumber: number;
|
|
|
- questionsCount: number;
|
|
|
- }>;
|
|
|
+ elements: CardElement[];
|
|
|
}>;
|
|
|
}
|
|
|
|
|
@@ -218,6 +237,8 @@ export default function useDraw(winId: number) {
|
|
|
objectiveData.answers.forEach((item) => {
|
|
|
answerMap[`${item.mainNumber}_${item.subNumber}`] = {
|
|
|
answer: item.answer,
|
|
|
+ totalScore: item.totalScore,
|
|
|
+ score: item.score,
|
|
|
isRight: item.answer === item.standardAnswer,
|
|
|
};
|
|
|
});
|
|
@@ -291,6 +312,7 @@ export default function useDraw(winId: number) {
|
|
|
.flat();
|
|
|
|
|
|
const markDeailList = parseMarkDetailList(originImgs);
|
|
|
+ const objectiveAnswerTagList = parseObjectiveAnswerTags(originImgs);
|
|
|
|
|
|
for (let i = 0; i < originImgs.length; i++) {
|
|
|
const img = originImgs[i];
|
|
@@ -308,6 +330,10 @@ export default function useDraw(winId: number) {
|
|
|
const answerTags = paserRecogData(i);
|
|
|
drawTrackList.push(...answerTags);
|
|
|
drawTrackList.push(...(markDeailList[i] || []));
|
|
|
+ const oTags = (objectiveAnswerTagList[i] || []).map(
|
|
|
+ (tag) => tag.trackItem
|
|
|
+ );
|
|
|
+ drawTrackList.push(...oTags);
|
|
|
drawTrackList.push(getTotalTrack(img));
|
|
|
|
|
|
trackData[i] = {
|
|
@@ -589,10 +615,10 @@ export default function useDraw(winId: number) {
|
|
|
dataArr.push({
|
|
|
type: 'text',
|
|
|
option: {
|
|
|
- x: area.x + area.w - Math.ceil(tContLen * 30),
|
|
|
+ x: area.x + area.w - Math.ceil(tContLen * trackTextFontSize),
|
|
|
y: area.y,
|
|
|
text: tCont,
|
|
|
- fontSize: 30,
|
|
|
+ fontSize: trackTextFontSize,
|
|
|
},
|
|
|
});
|
|
|
});
|
|
@@ -661,10 +687,10 @@ export default function useDraw(winId: number) {
|
|
|
dataArr.push({
|
|
|
type: 'text',
|
|
|
option: {
|
|
|
- x: area.x + area.w - Math.ceil(tContLen * 30),
|
|
|
+ x: area.x + area.w - Math.ceil(tContLen * trackTextFontSize),
|
|
|
y: area.y,
|
|
|
text: tCont,
|
|
|
- fontSize: 30,
|
|
|
+ fontSize: trackTextFontSize,
|
|
|
},
|
|
|
});
|
|
|
});
|
|
@@ -822,6 +848,98 @@ export default function useDraw(winId: number) {
|
|
|
}
|
|
|
// answer tag ----- end->
|
|
|
|
|
|
+ // objective answer tag ----- start->
|
|
|
+ interface ObjectiveAnswerTagItem {
|
|
|
+ id: string;
|
|
|
+ mainNumber: number;
|
|
|
+ subNumbers: string;
|
|
|
+ score: number;
|
|
|
+ totalScore: number;
|
|
|
+ trackItem: DrawTrackItem;
|
|
|
+ }
|
|
|
+ function parseObjectiveAnswerTags(images: ImageItem[]) {
|
|
|
+ const objectiveAnswerTags: Array<ObjectiveAnswerTagItem[]> = [];
|
|
|
+
|
|
|
+ if (!cardData?.length) return objectiveAnswerTags;
|
|
|
+
|
|
|
+ cardData.forEach((page, pindex) => {
|
|
|
+ if (!objectiveAnswerTags[pindex]) objectiveAnswerTags[pindex] = [];
|
|
|
+ const img = images[pindex] as ImageItem;
|
|
|
+
|
|
|
+ page.columns.forEach((column) => {
|
|
|
+ column.elements.forEach((element) => {
|
|
|
+ if (element.type !== 'FILL_QUESTION') return;
|
|
|
+
|
|
|
+ const ogroup = objectiveAnswerTags.find((tgroup) =>
|
|
|
+ tgroup.some((oitem) => oitem.id === element.parent.id)
|
|
|
+ );
|
|
|
+ if (ogroup) return;
|
|
|
+
|
|
|
+ const parent = element.parent;
|
|
|
+ const oaTagItem: ObjectiveAnswerTagItem = {
|
|
|
+ id: parent.id,
|
|
|
+ mainNumber: parent.topicNo,
|
|
|
+ subNumbers: `${parent.startNumber}~${
|
|
|
+ parent.startNumber + parent.questionsCount - 1
|
|
|
+ }`,
|
|
|
+ score: 0,
|
|
|
+ totalScore: 0,
|
|
|
+ trackItem: {} as DrawTrackItem,
|
|
|
+ };
|
|
|
+ // 位置
|
|
|
+ const area = { x: 0, y: 0, w: 0.44 };
|
|
|
+ page.exchange.fill_area.forEach((fa) => {
|
|
|
+ fa.items.forEach((fitem) => {
|
|
|
+ if (
|
|
|
+ fitem.main_number === oaTagItem.mainNumber &&
|
|
|
+ fitem.sub_number === parent.startNumber
|
|
|
+ ) {
|
|
|
+ const [x, y] = fitem.options[0];
|
|
|
+ area.x = x;
|
|
|
+ area.y = y;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ area.x = (area.x - 0.015) * img.width;
|
|
|
+ area.y = (area.y - 0.04) * img.height;
|
|
|
+ area.w *= img.width;
|
|
|
+
|
|
|
+ // 分数统计
|
|
|
+ const questions: Array<{ score: number; totalScore: number }> = [];
|
|
|
+ for (let i = 0; i < parent.questionsCount; i++) {
|
|
|
+ const qans = answerMap[
|
|
|
+ `${parent.topicNo}_${i + parent.startNumber}`
|
|
|
+ ] || { score: 0, totalScore: 0 };
|
|
|
+ questions[i] = {
|
|
|
+ score: qans.score,
|
|
|
+ totalScore: qans.totalScore,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ oaTagItem.score = calcSum(questions.map((q) => q.score || 0));
|
|
|
+ oaTagItem.totalScore = calcSum(
|
|
|
+ questions.map((q) => q.totalScore || 0)
|
|
|
+ );
|
|
|
+ const tCont = `得分:${oaTagItem.score},满分:${oaTagItem.totalScore}`;
|
|
|
+ const tContLen = strGbLen(tCont) / 2;
|
|
|
+ oaTagItem.trackItem = {
|
|
|
+ type: 'text',
|
|
|
+ option: {
|
|
|
+ x: area.x + area.w - Math.ceil(tContLen * trackTextFontSize),
|
|
|
+ y: area.y,
|
|
|
+ text: tCont,
|
|
|
+ fontSize: trackTextFontSize,
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ objectiveAnswerTags[pindex].push(oaTagItem);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ return objectiveAnswerTags;
|
|
|
+ }
|
|
|
+ // objective answer tag ----- end->
|
|
|
+
|
|
|
return {
|
|
|
runTask,
|
|
|
getTrackTask,
|