209 lines
6.6 KiB
TypeScript
209 lines
6.6 KiB
TypeScript
import CalculationPracticeDraw from '../shared/service/calculationPracticeDraw';
|
|
import {
|
|
createMathPage,
|
|
CanvasDataState,
|
|
} from '../shared/common/mathPageMixin';
|
|
|
|
type OperationType = 'addition' | 'subtraction' | 'mixed';
|
|
|
|
createMathPage({
|
|
canvas: null as Canvas | null,
|
|
ctx: null as RenderingContext | null,
|
|
boxHeight: 0,
|
|
boxWidth: 0,
|
|
drawService: null as CalculationPracticeDraw | null,
|
|
calculationPracticeData: null as {
|
|
problems: Array<{
|
|
left: number;
|
|
operator: '+' | '-';
|
|
right: number;
|
|
result: number;
|
|
}>;
|
|
} | null,
|
|
|
|
data: {
|
|
pageTitle: '计算练习题',
|
|
functionId: '',
|
|
hasContent: false,
|
|
showShareDialog: false,
|
|
operationType: 'addition' as OperationType, // 运算类型:加法、减法、混合
|
|
currentMode: 'within-10', // 默认10以内
|
|
currentModeName: '10以内',
|
|
typeActions: [
|
|
{ name: '10以内', value: 'within-10' },
|
|
{ name: '20以内', value: 'within-20' },
|
|
{ name: '50以内', value: 'within-50' },
|
|
{ name: '100以内', value: 'within-100' },
|
|
],
|
|
} as CanvasDataState & {
|
|
operationType: OperationType;
|
|
currentMode: string;
|
|
currentModeName: string;
|
|
typeActions: Array<{ name: string; value: string }>;
|
|
},
|
|
|
|
onLoad(options: { id?: string; type?: string }) {
|
|
const functionId = options.id || 'practice-addition';
|
|
|
|
// 根据 functionId 确定运算类型
|
|
let operationType: OperationType = 'addition';
|
|
if (functionId === 'practice-subtraction') {
|
|
operationType = 'subtraction';
|
|
} else if (functionId === 'practice-mixed') {
|
|
operationType = 'mixed';
|
|
} else if (options.type) {
|
|
operationType = options.type as OperationType;
|
|
}
|
|
|
|
let pageTitle = '计算练习题';
|
|
if (operationType === 'addition') {
|
|
pageTitle = '加法运算';
|
|
} else if (operationType === 'subtraction') {
|
|
pageTitle = '减法运算';
|
|
} else if (operationType === 'mixed') {
|
|
pageTitle = '混合运算';
|
|
}
|
|
|
|
this.setData({
|
|
operationType,
|
|
pageTitle,
|
|
});
|
|
this.initPageInfo(functionId, pageTitle);
|
|
},
|
|
|
|
onReady() {
|
|
this.initCanvas({
|
|
createDrawService: (
|
|
canvas: Canvas,
|
|
ctx: RenderingContext,
|
|
options?: Record<string, any>,
|
|
) => {
|
|
return new CalculationPracticeDraw(canvas, ctx, options);
|
|
},
|
|
drawServiceOptions: {},
|
|
onCanvasReady: () => {
|
|
// 初始随机生成
|
|
this.onRandom();
|
|
},
|
|
});
|
|
},
|
|
|
|
/**
|
|
* 绘制Canvas内容
|
|
*/
|
|
async drawCanvas() {
|
|
if (!this.ctx || !this.drawService || !this.calculationPracticeData) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await this.drawService.draw(this.calculationPracticeData);
|
|
this.setData({ hasContent: true });
|
|
} catch (error) {
|
|
console.error('绘制失败:', error);
|
|
this.setData({ hasContent: false });
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 随机生成
|
|
*/
|
|
onRandom() {
|
|
// 根据当前模式确定最大值
|
|
let maxValue = 10;
|
|
if (this.data.currentMode === 'within-20') {
|
|
maxValue = 20;
|
|
} else if (this.data.currentMode === 'within-50') {
|
|
maxValue = 50;
|
|
} else if (this.data.currentMode === 'within-100') {
|
|
maxValue = 100;
|
|
}
|
|
|
|
const problems: Array<{
|
|
left: number;
|
|
operator: '+' | '-';
|
|
right: number;
|
|
result: number;
|
|
}> = [];
|
|
const usedProblems = new Set<string>();
|
|
let attempts = 0;
|
|
const maxAttempts = 2000;
|
|
|
|
const targetCount = 11 * 3; // 12行3列 = 36道题
|
|
|
|
while (problems.length < targetCount && attempts < maxAttempts) {
|
|
attempts++;
|
|
|
|
let left: number;
|
|
let right: number;
|
|
let operator: '+' | '-';
|
|
let result: number;
|
|
|
|
// 根据运算类型生成题目
|
|
if (this.data.operationType === 'addition') {
|
|
// 加法:left + right <= maxValue
|
|
left = Math.floor(Math.random() * (maxValue - 1)) + 1; // 1 到 maxValue-1
|
|
const maxRight = maxValue - left;
|
|
right = Math.floor(Math.random() * maxRight) + 1; // 1 到 maxRight
|
|
operator = '+';
|
|
result = left + right;
|
|
} else if (this.data.operationType === 'subtraction') {
|
|
// 减法:left - right >= 0, left <= maxValue
|
|
left = Math.floor(Math.random() * maxValue) + 1; // 1 到 maxValue
|
|
right = Math.floor(Math.random() * left) + 1; // 1 到 left
|
|
operator = '-';
|
|
result = left - right;
|
|
} else {
|
|
// 混合运算:随机选择加法或减法
|
|
const isAddition = Math.random() < 0.5;
|
|
if (isAddition) {
|
|
left = Math.floor(Math.random() * (maxValue - 1)) + 1;
|
|
const maxRight = maxValue - left;
|
|
right = Math.floor(Math.random() * maxRight) + 1;
|
|
operator = '+';
|
|
result = left + right;
|
|
} else {
|
|
left = Math.floor(Math.random() * maxValue) + 1;
|
|
right = Math.floor(Math.random() * left) + 1;
|
|
operator = '-';
|
|
result = left - right;
|
|
}
|
|
}
|
|
|
|
// 使用 "left,operator,right" 作为唯一标识,避免重复
|
|
const problemKey = `${left},${operator},${right}`;
|
|
if (usedProblems.has(problemKey)) {
|
|
continue;
|
|
}
|
|
|
|
usedProblems.add(problemKey);
|
|
problems.push({
|
|
left,
|
|
operator,
|
|
right,
|
|
result,
|
|
});
|
|
}
|
|
|
|
if (problems.length < targetCount) {
|
|
console.warn(
|
|
`只生成了 ${problems.length} 道题目,可能符合条件的题目组合不足`,
|
|
);
|
|
}
|
|
|
|
this.calculationPracticeData = { problems };
|
|
this.drawCanvas();
|
|
},
|
|
|
|
/** 选择类型 */
|
|
onSelectType(event: any) {
|
|
const { name, value } = event.detail;
|
|
this.setData({
|
|
currentMode: value,
|
|
currentModeName: name,
|
|
});
|
|
// 重新生成数据
|
|
this.onRandom();
|
|
},
|
|
});
|