feat:V2.5.5方格推理

This commit is contained in:
R524809
2025-12-19 10:34:30 +08:00
parent 99686e30bd
commit 78d98164e5
10 changed files with 651 additions and 4 deletions
@@ -0,0 +1,261 @@
import GridReasoningDraw from '../shared/service/gridReasoningDraw';
import { createFocusPage } from '../shared/common/focusPageMixin';
import {
GridReasoningData,
GridPosition,
} from '../shared/service/gridReasoningDraw';
import { NUMBER_COLORS } from '../../constants/colors';
createFocusPage({
canvas: null as Canvas | null,
ctx: null as RenderingContext | null,
boxHeight: 0,
boxWidth: 0,
drawService: null as GridReasoningDraw | null,
gridData: null as GridReasoningData | null,
data: {
pageTitle: '方格推理',
functionId: '',
hasContent: false,
showShareDialog: false,
currentOperatorType: 'mixed', // 'addition', 'subtraction', 'mixed'
currentOperatorTypeName: '混合运算',
operatorTypeActions: [
{ name: '加法运算', value: 'addition' },
{ name: '减法运算', value: 'subtraction' },
{ name: '混合运算', value: 'mixed' },
],
},
onLoad(options: { id?: string }) {
const functionId = options.id || 'grid-reasoning';
this.setData({
functionId,
});
this.initPageInfo(functionId, '方格推理');
},
onReady() {
this.initCanvas({
createDrawService: (
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) => {
return new GridReasoningDraw(canvas, ctx, options);
},
drawServiceOptions: {
title: this.data.pageTitle,
subTitle: '仔细观察,推理出合并方格并连线',
functionId: this.data.functionId,
},
onCanvasReady: () => {
// 初始随机生成
this.onRandom();
},
});
},
/**
* 绘制Canvas内容
*/
async drawCanvas() {
if (!this.ctx || !this.drawService || !this.gridData) {
return;
}
try {
await this.drawService.draw(this.gridData);
this.setData({ hasContent: true });
} catch (error) {
console.error('绘制失败:', error);
this.setData({ hasContent: false });
}
},
/**
* 选择运算类型
*/
onSelectType(event: any) {
const { name, value } = event.detail;
this.setData({
currentOperatorType: value,
currentOperatorTypeName: name,
});
// 重新生成题目
this.onRandom();
},
/**
* 随机生成
*/
onRandom() {
// 随机选择一种颜色
const colorKeys = Object.keys(NUMBER_COLORS).map(Number);
const randomColorKey =
colorKeys[Math.floor(Math.random() * colorKeys.length)];
const selectedColor = NUMBER_COLORS[randomColorKey];
const rows: Array<{
grid1: GridPosition[];
grid2: GridPosition[];
operator: '+' | '-';
result: GridPosition[];
}> = [];
const operatorType = this.data.currentOperatorType;
// 生成5行的数据
for (let i = 0; i < 5; i++) {
// 根据选中的运算类型选择运算符
let operator: '+' | '-';
if (operatorType === 'addition') {
operator = '+';
} else if (operatorType === 'subtraction') {
operator = '-';
} else {
// 混合运算:随机选择运算符
operator = Math.random() > 0.5 ? '+' : '-';
}
// 生成第一个网格的涂色位置
// 如果是减法运算,第一个网格至少要有2个位置
let grid1Count: number;
if (operator === '-') {
grid1Count = Math.floor(Math.random() * 8) + 2; // 2-9个位置
} else {
grid1Count = Math.floor(Math.random() * 9) + 1; // 1-9个位置
}
const grid1Positions = this.generateRandomPositions(grid1Count);
let grid2Positions: GridPosition[];
let resultPositions: GridPosition[];
if (operator === '+') {
// 加法:生成第二个网格的涂色位置(至少1个)
const grid2Count = Math.floor(Math.random() * 9) + 1;
grid2Positions = this.generateRandomPositions(grid2Count);
// 结果 = 并集
resultPositions = this.unionPositions(
grid1Positions,
grid2Positions,
);
} else {
// 减法:生成第二个网格的涂色位置(必须少于第一个)
const maxGrid2Count = grid1Count - 1;
const grid2Count =
Math.floor(Math.random() * maxGrid2Count) + 1;
grid2Positions = this.generateRandomPositions(grid2Count);
// 结果 = 差集
resultPositions = this.subtractPositions(
grid1Positions,
grid2Positions,
);
}
rows.push({
grid1: grid1Positions,
grid2: grid2Positions,
operator: operator as '+' | '-',
result: resultPositions,
});
}
// 生成右侧答案选项
// 右侧展示左侧5行的结果(result),顺序随机
const answerOptions: Array<{
positions: GridPosition[];
rowIndex: number;
}> = [];
for (let i = 0; i < 5; i++) {
answerOptions.push({
positions: rows[i].result,
rowIndex: i,
});
}
// 随机打乱顺序
answerOptions.sort(() => Math.random() - 0.5);
this.gridData = {
rows,
answerOptions,
color: selectedColor,
};
this.drawCanvas();
},
/**
* 生成随机位置(不重复)
*/
generateRandomPositions(count: number): GridPosition[] {
const allPositions: GridPosition[] = [];
for (let y = 0; y < 3; y++) {
for (let x = 0; x < 3; x++) {
allPositions.push({ x, y });
}
}
// 随机打乱
const shuffled = [...allPositions].sort(() => Math.random() - 0.5);
// 返回前count个
return shuffled.slice(0, count);
},
/**
* 计算位置的并集
*/
unionPositions(pos1: GridPosition[], pos2: GridPosition[]): GridPosition[] {
const set = new Set<string>();
const result: GridPosition[] = [];
// 添加第一个数组的位置
for (const pos of pos1) {
const key = `${pos.x},${pos.y}`;
if (!set.has(key)) {
set.add(key);
result.push(pos);
}
}
// 添加第二个数组的位置(去重)
for (const pos of pos2) {
const key = `${pos.x},${pos.y}`;
if (!set.has(key)) {
set.add(key);
result.push(pos);
}
}
return result;
},
/**
* 计算位置的差集(pos1 - pos2
*/
subtractPositions(
pos1: GridPosition[],
pos2: GridPosition[],
): GridPosition[] {
const set2 = new Set<string>();
for (const pos of pos2) {
set2.add(`${pos.x},${pos.y}`);
}
const result: GridPosition[] = [];
for (const pos of pos1) {
const key = `${pos.x},${pos.y}`;
if (!set2.has(key)) {
result.push(pos);
}
}
return result;
},
});