佛系结对编程---四则运算(Core 第四组)
----by core 第四组 ( 邹卫其 范力 )
一. 项目介绍
1.
2. 将四则运算的计算功能包装在一个模块中( class 或 DLL)
3. 将 core 模块通过一定的 API 接口 (Application Programming Interface) 来和 UI 组对接
三. 代码实现
1. 定义 Core 类(封装成大类)
1 class Core 2 { 3 private: 4 int que_num = 100; //题目数量 5 int data_num = 10; //操作数数量 6 int range = 5; //计算的数值范围 7 int opr_type = 3; //操作符种类 0.加减 1.加减乘 2.加减乘除 3.加减乘除乘方 8 int data_type = 1; //0整数 1小数 2分数 9 int accuracy = 2; 10 string* que = new string[que_num + 1]; 11 string* ans = new string[que_num + 1]; 12 public: 13 void set_que_num(int a) { que_num = a; } 14 void set_data_num(int a) { data_num = a; } 15 void set_range(int a) { range = a; } 16 void set_opr_type(int a) { opr_type = a; } 17 void set_data_type(int a) { data_type = a; } 18 void set_accuracy(int a) { accuracy = a; } 19 int get_que_num() { return que_num; } 20 int get_data_num() { return data_num; } 21 int get_range() { return range; } 22 int get_opr_type() { return opr_type; } 23 int get_data_type() { return data_type; } 24 int get_accuracy() { return accuracy; } 25 string *getQue(); 26 string *getAns(); 27 private: 28 string expstring(Node *root); 29 Node *creatOptree(); 30 Node calc(Node *root); 31 void previsite(Node *head); 32 char operat(); 33 char int_operat(); 34 int get_factor(int a); 35 };
2. 设置类的参数并调用示例
1 int main() 2 { 3 Core cal; 4 string *q, *a; 5 6 cal.set_data_num(10); 7 cal.set_que_num(100); 8 cal.set_range(10); 9 cal.set_opr_type(3); 10 cal.set_data_type(1); 11 cal.set_accuracy(3); 12 13 q = cal.getQue(); 14 a = cal.getAns(); 15 for (int i = 1; i <= cal.get_que_num(); i++) 16 { 17 cout << q[i] << " = " << a[i] << endl << endl; 18 } 19 20 system("pause"); 21 return 0; 22 }
3. 定义节点 Node 类
1 class Node 2 { 3 public: 4 Node() { top = -1; bottom = -1; operat = 0; left = NULL; right = NULL; } 5 Node(int t, int b, char opr) { top = t; bottom = b; operat = opr; left = NULL; right = NULL; } 6 void simp(); 7 int gcd(int p, int q); 8 Node operator + (Node n2); 9 Node operator - (Node n2); 10 Node operator * (Node n2); 11 Node operator / (Node n2); 12 Node operator ^ (Node n2); 13 Node operator = (Node n2); 14 15 public: 16 int top; 17 int bottom; 18 char operat; 19 class Node *left; 20 class Node *right; 21 22 }; 23 24 Node Node::operator + (Node n2) 25 { 26 Node n; 27 n.top = top*n2.bottom + bottom*n2.top; 28 n.bottom = bottom*n2.bottom; 29 n.operat = 0; 30 n.left = NULL; 31 n.right = NULL; 32 n.simp(); 33 return n; 34 } 35 Node Node::operator - (Node n2) 36 { 37 Node n; 38 n.top = top*n2.bottom - bottom*n2.top; 39 n.bottom = bottom*n2.bottom; 40 n.operat = 0; 41 n.left = NULL; 42 n.right = NULL; 43 n.simp(); 44 return n; 45 } 46 Node Node::operator * (Node n2) 47 { 48 Node n; 49 n.top = top*n2.top; 50 n.bottom = bottom*n2.bottom; 51 n.operat = 0; 52 n.left = NULL; 53 n.right = NULL; 54 n.simp(); 55 return n; 56 } 57 Node Node::operator / (Node n2) 58 { 59 Node n; 60 n.top = top*n2.bottom; 61 n.bottom = bottom*n2.top; 62 n.operat = 0; 63 n.left = NULL; 64 n.right = NULL; 65 n.simp(); 66 return n; 67 } 68 Node Node::operator ^ (Node n2) 69 { 70 Node n; 71 n.top = (int)pow(top, n2.top); 72 n.bottom = (int)pow(bottom, n2.top); 73 n.operat = 0; 74 n.left = NULL; 75 n.right = NULL; 76 n.simp(); 77 78 return n; 79 } 80 Node Node::operator = (Node n2) 81 { 82 top = n2.top; 83 bottom = n2.bottom; 84 operat = n2.operat; 85 return Node(n2.top, n2.bottom, 0); 86 }
4. 随机生成一颗算数表达式树
1 Node* Core::creatOptree() 2 { 3 Node *head = NULL, *p = NULL, *q = NULL; 4 int i = 0, j = 0; 5 head = new Node; 6 head->operat = '+'; 7 8 for (i = 1, j = 0; i < data_num - 1; i++) 9 { 10 p = head; 11 while (p) 12 { 13 if (rand() % 2) { 14 if (p->left) p = p->left; 15 else { 16 q = new Node; 17 if (data_type == 0) q->operat = int_operat(); 18 else q->operat = operat(); 19 p->left = q; 20 break; 21 } 22 } 23 else { 24 if (p->right) p = p->right; 25 else { 26 q = new Node; 27 if (data_type == 0) q->operat = int_operat(); 28 else q->operat = operat(); 29 p->right = q; 30 break; 31 } 32 } 33 }//end while 34 }//end if 35 return head; 36 } 37 38 void Core::previsite(Node *head) 39 { 40 if (!head) return; 41 class Node *q = NULL, *p = NULL; 42 if (head->operat && opr_type == 3 && !head->left && !head->right) 43 { 44 int temp = 0; 45 temp = rand() % 4; 46 if (temp == 0) head->operat = '^'; 47 } 48 49 if (head->operat && data_type == 0 && (opr_type == 2 || opr_type == 3) && !head->left && !head->right) 50 { 51 int temp = 0; 52 temp = rand() % 4; 53 if (temp == 0) head->operat = '/'; 54 } 55 56 if (head->operat && !head->left) 57 { 58 p = new Node; 59 //reset(q); 60 p->bottom = rand() % range + 1; 61 p->top = rand() % range + 1; 62 if (data_type == 0) p->bottom = 1; //整数 63 if (data_type == 0 && head->operat == '/') p->top = rand() % range + 1; 64 if (data_type == 1) //小数 65 { 66 p->bottom = 20; 67 p->top = rand() % (20 * range); 68 } 69 if (head->operat == '^') 70 { 71 int min = (range < 6) ? range : 6; 72 p->bottom = 1; 73 p->top = rand() % min + 1; 74 } 75 head->left = p; 76 } 77 if (head->operat && !head->right) 78 { 79 q = new Node; 80 //reset(q); 81 q->bottom = rand() % range + 1; 82 q->top = rand() % range + 1; 83 if (data_type == 0) q->bottom = 1; //整数 84 if (data_type == 0 && head->operat == '/') q->top = get_factor(head->left->top); 85 if (data_type == 1) //小数 86 { 87 q->bottom = 20; 88 q->top = rand() % (20 * range); 89 } 90 if (head->operat == '^') //乘方 91 { 92 int min = (range <= 5) ? range : 5; 93 q->bottom = 1; 94 q->top = rand() % min + 1; 95 } 96 head->right = q; 97 } 98 previsite(head->left); 99 previsite(head->right); 100 101 }
5. 计算表达式树数值
1 Node Core:: calc(Node *root) //计算树的值 2 { 3 Node answer; 4 if (root == NULL) 5 return answer; 6 char opr = root->operat; 7 8 if (opr == 0) 9 { 10 return *root; 11 } 12 else if (opr == '+') 13 { 14 return calc(root->left) + calc(root->right); 15 } 16 else if (opr == '-') 17 { 18 answer = (calc(root->left) - calc(root->right)); 19 if (answer.top < 0) 20 { 21 Node *temp = root->left; 22 root->left = root->right; 23 root->right = temp; 24 answer.top *= -1; 25 } 26 return answer; 27 } 28 else if (opr == '*') 29 { 30 return calc(root->left) * calc(root->right); 31 } 32 33 else if (opr == '/') 34 { 35 if (data_type == 0) 36 { 37 38 } 39 return calc(root->left) / calc(root->right); 40 } 41 42 else if (opr == '^') 43 { 44 return calc(root->left) ^ calc(root->right); 45 } 46 else 47 return answer; 48 }
6. 打印中缀表达式
1 string Core::expstring(Node *root) //生成中缀表达式 分子分母间用 | 2 { 3 if (root == NULL) 4 return que[0]; 5 if (root->left) 6 { 7 if ((root->left->operat == '+' || root->left->operat == '-') && (root->operat == '*' || root->operat == '/')) 8 { 9 que[0] += "( "; 10 expstring(root->left); 11 que[0] += ") "; 12 } 13 else if (root->operat == '^' && root->left->operat) 14 { 15 que[0] += "( "; 16 expstring(root->left); 17 que[0] += ") "; 18 } 19 else 20 expstring(root->left); 21 } 22 23 if (root->operat == 0) 24 { 25 if (data_type == 1) 26 { 27 double t = 1.0 * root->top / root->bottom; 28 stringstream s1; 29 s1 << t; 30 que[0] += s1.str(); 31 que[0] += " "; 32 } 33 else 34 { 35 stringstream s2; 36 s2 << root->top; 37 que[0] += s2.str(); 38 if (root->bottom > 1) 39 { 40 que[0] += "|"; 41 stringstream s3; 42 s3 << root->bottom; 43 que[0] += s3.str(); 44 } 45 que[0] += " "; 46 } 47 } 48 else 49 { 50 que[0] += root->operat; 51 que[0] += " "; 52 } 53 54 if (root->right) 55 { 56 if ((root->operat == '-' || root->operat == '*') && (root->right->operat == '-' || root->right->operat == '+')) 57 { 58 que[0] += "( "; 59 expstring(root->right); 60 que[0] += ") "; 61 } 62 else if (root->operat == '/' && (root->right->operat && root->right->operat != '^')) 63 { 64 que[0] += "( "; 65 expstring(root->right); 66 que[0] += ") "; 67 } 68 else if (root->operat == '^'&& root->right->operat) 69 { 70 que[0] += "( "; 71 expstring(root->right); 72 que[0] += ") "; 73 } 74 else 75 expstring(root->right); 76 } 77 return que[0]; 78 }
7. 生成题目 string 数组
1 string* Core::getQue() 2 { 3 Node *head, result; 4 que = new string[que_num + 1]; 5 ans = new string[que_num + 1]; 6 for (int i = 1; i <= que_num; i++) 7 { 8 head = creatOptree(); 9 previsite(head); 10 result = calc(head); 11 result.simp(); 12 if (result.bottom == 0 || result.top < 0) 13 i--; 14 else 15 { 16 que[0] = ""; 17 que[i] = expstring(head); 18 if (data_type == 1) 19 { 20 double t = 1.0 * result.top / result.bottom; 21 stringstream s1; 22 s1 << t; 23 ans[i] += s1.str(); 24 } 25 else 26 { 27 stringstream s2; 28 s2 << result.top; 29 ans[i] += s2.str(); 30 if (result.bottom > 1) 31 { 32 ans[i] += "|"; 33 stringstream s3; 34 s3 << result.bottom; 35 ans[i] += s3.str(); 36 } 37 } 38 } 39 } 40 return que; 41 }
8. 生成答案 string 数组
1 string* Core::getAns() 2 { 3 if (data_type == 1) 4 { 5 for (int i = 1; i <= que_num; i++) 6 { 7 for (int j = 0; ans[i][j]; j++) 8 if (ans[i][j] == '.') 9 { 10 for (size_t k = j + accuracy + 1; k < ans[i].length(); k++) 11 ans[i][k] = '\0'; 12 break; 13 } 14 } 15 } 16 return ans; 17 }
四. 测试
以下测试样例约定生成 20 道题目,每题 10 个运算数,数值范围 0~10,在加、减、乘、除、乘方模式。
1. 整数
1 ( 3 - 8 / 4 ) * ( 10 + 1 ^ 3 ) + 4 ^ 4 - ( 2 + 4 ) 2 = 261 3 5 / 1 + 1 - 5 + 9 * 10 - ( 10 + 5 - 4 * 2 ) 4 = 84 5 ( 6 - 4 + 8 ) * ( 10 - ( 5 ^ 1 - 2 ) ) + 5 + 9 + 3 6 = 87 7 5 * ( 10 * 7 - 7 ) - 2 / 1 + 9 + 4 ^ 4 + 4 8 = 582 9 9 * 3 ^ 2 + 4 * 3 + 7 * ( 9 + ( 10 - 7 ) * 2 ) 10 = 198 11 6 * ( 6 * 9 - 5 ) * 9 + ( 8 * 10 + 8 - 4 ) * 10 12 = 3486 13 ( 2 + 7 ) * ( 6 - 4 ) + ( 10 / 5 + 10 - 4 ) * 9 * 6 14 = 450 15 ( 3 + 4 * 4 ) * 4 + 1 ^ 1 * ( 7 / 1 + 1 / 1 ) 16 = 84 17 10 - 7 / 1 - ( 9 - 8 ) + 4 ^ 5 * ( 8 - 3 / 1 ) 18 = 5122 19 1 * 5 - 1 - 9 / 3 + 2 / 1 * 4 * 1 ^ 3 20 = 9 21 3 / 1 + 10 + 3 / 1 + 2 * 10 + 4 - ( 8 + 6 ) 22 = 26 23 3 * 2 * ( 4 / 2 + 5 ) + 3 - ( 6 - 3 ) + 9 - 1 24 = 50 25 2 * ( 8 - 4 + 1 ) + 1 ^ 5 + 3 + 8 * 4 - 7 26 = 39 27 7 + 10 - 4 - 2 + ( 10 + 6 ) * ( 1 ^ 3 + 4 / 2 ) 28 = 59 29 ( 1 + 9 - 7 / 1 ) * 9 * 10 + 7 * 6 * ( 6 - 2 ) 30 = 438 31 2 * ( 7 - 2 ) - ( 5 - 9 / 3 ) + 1 * 5 * 3 * 3 32 = 53 33 9 + 4 + 2 / 1 * 4 / 2 + 2 * 9 - 9 / 3 34 = 32 35 ( 2 ^ 4 + 7 / 1 ) * ( 2 + 9 * 9 ) + 2 * ( 4 + 4 ) 36 = 1925 37 ( 5 + 4 ^ 1 ) * 2 ^ 4 * 4 + 3 + 8 + 5 / 1 38 = 592 39 9 * 9 / 3 + ( 8 + 3 + 9 ) * ( 3 / 1 - 10 / 5 ) 40 = 47
2. 小数(精度为 3)
1 ( 1.05 - 1 ^ 3 ) / ( 1.75 * ( 6.1 - 3.2 ) ) + 3.4 + 3.1 + 6.15 + 8.9 2 = 21.559 3 ( 6.85 + 4.1 ) * 7.2 + 1.65 / ( 6 ^ 5 * 2.9 + 1.45 + 5.6 + 8.05 ) 4 = 78.840 5 ( 9.55 / ( 7.95 - 7.4 ) - 0.65 ) / 7.3 + ( 0.1 + 1.8 ) / ( 9.8 - 3.4 / 6.7 ) 6 = 2.494 7 1.2 / ( 6.15 + 5.15 - 9.75 - 0.45 ) + 2.9 / ( 9.9 / 9.9 ) * 1.1 / 1.9 8 = 2.769 9 ( 3.8 - 1.05 ) * 3.75 / 2 ^ 5 + ( 9.25 + 4.4 ) * 7.85 * 6 ^ 4 10 = 138870 11 ( 4.1 / ( 5.05 * 9.3 ) + 9.25 - 0.4 ) * 2 ^ 2 + 1.1 - ( 2.5 - 2.2 ) 12 = 36.549 13 3.7 + 6 ^ 4 + 9.6 * 4 + ( 8.6 - 7.15 - 0.1 ) * ( 1.6 + 6.25 ) 14 = 1348.7 15 4.7 + 8.55 + 3.2 - 2.55 + ( 4.35 - 0.5 ) * ( 5.75 + ( 4.1 + 4.35 ) / 2.15 ) 16 = 51.168 17 ( 2 ^ 5 - 7.65 ) * 2 ^ 4 + 7.85 / 5.4 / ( 0.05 * 9.65 * 7 ) 18 = 390.03 19 7.95 - 6.45 + 1 ^ 3 + 8.15 * 5.55 + ( 3.75 + 7.1 ) / ( 8.75 - 1.05 ) 20 = 49.141 21 3 ^ 4 - 0.55 / 3.9 + 6.6 / 1 ^ 3 * ( 7 + 6.75 ) / 7.25 22 = 93.376 23 ( 2 ^ 4 - 0.05 ) / ( 3.15 - 0.2 ) + 8.55 - 8.2 + 1.6 * 8.75 + 5.65 24 = 25.406 25 3.6 / ( ( 8.45 - 1.15 ) / 8.5 + 1.4 * ( 7.15 - 3.15 ) ) + ( 1.05 + 4.4 ) * 9.4 26 = 51.787 27 ( 1.25 + 7.45 ) / ( 3 ^ 2 / 2 ^ 2 ) + 5 ^ 5 * 5 ^ 1 28 = 15628.9 29 5 ^ 5 - ( 4.45 + 2.65 + 2.15 ) + 0.1 * ( 8.45 - ( 9.6 - 7.25 ) * 0.4 ) 30 = 3116.5 31 2 ^ 1 + 5.5 - ( 4.1 - 1.95 ) + ( 7.05 - 4.45 ) * 9.4 - ( 1.4 - 0 ) 32 = 28.39 33 4 ^ 3 - 8.2 - ( 3.3 - 0.8 ) + 6.55 * 5.9 * 7.05 / ( 4.05 - 1.5 ) 34 = 160.142 35 3.3 + 9.8 / 7.9 + 2.9 * 4.9 + 9.6 - ( 3.9 + 2.4 ) * 8.75 / 6.8 36 = 20.243 37 4.45 - ( 9.25 + 0.75 - ( 4.65 + 5 ) ) + ( 8.95 + 9.1 ) * 1.3 - 8.05 / 7.9 38 = 26.546 39 8.1 / 0.75 / 3 ^ 1 + ( 8.35 - 6.6 ) * 2 ^ 4 / 5 ^ 2 40 = 4.72
3. 分数
1 ( 3|3 - 9|7 / 8|6 ) / ( 2|7 * ( 10|8 - 3|10 ) ) + 4|5 + 3|2 + 5|4 + 2|2 2 = 1779|380 3 2|7 * 9|4 / 1|10 + 5|4 * 7|5 + 7 / ( 1 ^ 4 + 9|9 + 10|3 ) 4 = 1063|112 5 2 - 7|5 - ( 3|2 - 5|6 ) * 6|7 + ( 8|8 - 2|8 ) * 8|8 * ( 6|4 - 10|10 ) 6 = 113|280 7 7 * ( 10|9 - 5|9 ) + ( 9|10 - 1|9 ) * 5|2 - ( 9|8 + 4|9 * 2|8 ) * 8|9 8 = 1543|324 9 9|4 / 9 * ( 9|10 - 8|10 ) / 9|7 / 1|9 + 3|3 - 3|9 / ( 9|8 - 1|10 ) 10 = 4181|4920 11 ( 10|3 - 7|8 ) / ( 1|3 * 4 ) + 9|2 + 10|2 + ( 3|4 - 3|6 ) * ( 8|8 - 7|9 ) 12 = 3283|288 13 ( 8|10 + 10|7 - ( 8|6 - 7|7 ) ) * ( 5|6 + 2|5 + 9|6 ) + 4|4 / 6|6 + 2|7 14 = 10184|1575 15 4|10 + 6 ^ 4 + 9|3 * 8|9 + 2|9 + 6|3 + 5|5 + 3|5 - 5|8 16 = 93763|72 17 3|3 + 8 - 5|7 - 2|6 - ( 3|4 - 4|6 ) + 4|6 * 1|2 * 1|5 / 4 18 = 276|35 19 1 ^ 1 * 8|7 * 9|4 + 5 ^ 3 / ( ( 8|6 + 9|10 ) / ( 3 * 4|3 ) ) 20 = 106206|469 21 ( 4 - 9|9 ) / ( 9 * 4|10 + 8|6 ) + 4 ^ 3 - 1|2 * 1 ^ 2 22 = 2372|37 23 10|4 - 6|10 - ( 7|3 - 4|6 ) + ( 5|5 - 3|5 ) / ( ( 3|10 + 8|4 ) * ( 6|2 - 9|8 ) ) 24 = 15|46 25 6|7 * ( 4 - 2|9 ) / ( 6|6 * 3|3 ) * 5|8 * 3|9 + 7|4 * ( 4 - 3|6 ) 26 = 3427|504 27 2|5 + 10|4 + 10|8 - 3|9 + 6 ^ 1 + ( 8|2 - 4|4 * 5|3 ) * 5|4 28 = 191|15 29 1 ^ 5 + 2|4 + 3 ^ 1 * 8|9 + 3|4 + 7|3 * 3|10 / 6|10 30 = 73|12 31 1 ^ 5 + 10|4 - ( 3|9 - 1|9 ) + ( 10 - 7|9 ) / 9|2 * ( 1 + 8|9 ) 32 = 10423|1458 33 5|6 * ( 4|6 + 7|3 ) * ( 4|7 / 5|10 - 3|9 ) + 7|6 / 2|7 * 6|3 / 7|6 34 = 379|42 35 5|4 / 5|4 * 7|4 * 2 ^ 1 + 9 * ( 6 / 5|2 + 4|7 - 3|10 ) 36 = 964|35 37 9|10 + 2 + 10|6 - 8|9 / ( 2|9 * 4|10 + 2 ) + 6|6 / 10 * 8|5 38 = 30323|7050 39 4 / ( 5|9 - 1|9 ) / ( 5|6 + 4|2 ) + 4|8 + 10|9 + 7|4 - ( 6|9 + 10|7 ) 40 = 19031|4284
4. 样例分析
可以看到,我们生成的算数表达式符合参数要求,结构均匀而随机,括号匹配无误,计算结果正确。
五. DLL 封装和对接
参考网上知识,采用 VS2017 创建 DLL 文件,在 .h 头文件中进行类的定义和相关声明,在 .cpp 文件中进行各种成员函数的定义。在完成 DLL 相关配置后,生成新的解决方案,生成相应的 .lib 和 .dll 文件。
编写测试程序,测试 DLL 文件,将 .h .lib 和 .dll 文件复制到相应文件夹,在头文件中引用 .h 文件,在资源文件引用 .lib 文件,在 main 函数中创建对象,引用成员函数,检测成功后给 UI 组初步对接。
与 UI 组进行 DLL 对接时,其中一组曾编译出现 “LNK2019 无法解析的外部符号” 的报错,后来排查得知是 x64 和 x86 平台差异引起,于是我们对 x86 和 x64 分别生成 .lib 和 .dll 文件,解决了这个问题。
六. 结对编程感悟
这次结对的过程中 zou 主要完成算术表达式的计算,中缀显示,类的封装,DLL 文件的生成;fan 主要完成算数表达式在各种情况下的生成,API 和博客的撰写。
这次编程非常佛系最后一天上午才完成,然后忙着和 UI 组对接,总的来说结对编程的效率远高于独立作业,我们将思路理顺之后编程非常高效,出现 bug 之后也能及时发现并解决。
面对再一次的编程任务,我们抱以一种佛系的心态,一开始并未着急编写,吸取上次经验,讨论了很多种方案,仔细分析优劣,最终理清思路并梳理了整体的框架,有条不紊地编写时并未出现太多意料之外的困难。
面对问题的处理方式是多种多样的,结对编程优势之一就是,两个人的积极性互相被调动,个人陷入局部困境导致整体目标变模糊的概率也大为减小,与之同时,不论焦急还是从容,死限 DDL 来临的速率是一个常数,所以不妨用更加佛系的心态,减少实际行动中漫无目的或毫无效率忙碌,更多地在思维活跃而清晰之下充分调用自身能力,稳健地去面对。
七. PSP 表格
Personal Software Process Stages | 预估耗时(分) | 实际耗时(分) |
---|---|---|
计划 | 10 | 10 |
· 估计这个任务需要多少时间 | 10 | 10 |
开发 | 1495 | 1540 |
· 需求分析 (包括学习新技术) | 2h * 60 | 3h * 60 |
· 生成设计文档 | 30 | 20 |
· 设计复审 (和同事审核设计文档) | 5 | 5 |
· 代码规范 (为目前的开发制定合适的规范) | 10 | 5 |
· 具体设计 | 30 | 30 |
· 具体编码 | 12h * 60 | 10h * 60 |
· 代码复审 | 30 | 40 |
· 测试(自我测试,修改代码,提交修改) | 10h * 60 | 11h * 60 |
报告 | 70 | 60 |
· 测试报告 | 30 | 30 |
· 计算工作量 | 10 | 10 |
· 事后总结, 并提出过程改进计划 | 30 | 20 |
1555 | 1620 |