diff --git a/package.json b/package.json index e2dbaedf..b0972fba 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "start": "wb start", "start-stg": "wb start --mode staging", "test": "wb test", + "test-unit": "wb test --unit", "test/ci-setup": "wb prisma reset", "typecheck": "wb typecheck" }, diff --git a/src/problems/problemData.ts b/src/problems/problemData.ts index 73551e55..1bad6393 100644 --- a/src/problems/problemData.ts +++ b/src/problems/problemData.ts @@ -3,14 +3,29 @@ export type CourseId = (typeof courseIds)[number]; export const problemIds = [ 'straight', + 'straight2', 'stepBack', + 'stepBack2', 'turnRight', - 'turnRightAndTurnLeft', + 'turnRight2', + 'turnLeftAndRight', + 'turnLeftAndRight2', + 'turnLeftAndRight3', + 'turnLeftAndRight4', 'square1', 'square2', + 'square3', + 'square4', 'variable', 'variable2', 'variable3', + 'variable4', + 'variable5', + 'variable6', + 'variable7', + 'variable8', + 'variable9', + 'variable10', 'while1', 'while2', 'for1', @@ -60,14 +75,29 @@ export const courseIdToName: Record = { export const problemIdToName: Record = { straight: '線を描こう(1)', - stepBack: '線を描こう(2)', - turnRight: '線を描こう(3)', - turnRightAndTurnLeft: '線を描こう(4)', + straight2: '線を描こう(2)', + stepBack: '線を描こう(3)', + stepBack2: '線を描こう(4)', + turnRight: '線を描こう(5)', + turnRight2: '線を描こう(6)', + turnLeftAndRight: '線を描こう(7)', + turnLeftAndRight2: '線を描こう(8)', + turnLeftAndRight3: '線を描こう(9)', + turnLeftAndRight4: '線を描こう(10)', square1: '図形を描こう(1)', square2: '図形を描こう(2)', + square3: '図形を描こう(3)', + square4: '図形を描こう(4)', variable: '変数を使おう(1)', variable2: '変数を使おう(2)', variable3: '変数を使おう(3)', + variable4: '変数を使おう(4)', + variable5: '変数を使おう(5)', + variable6: '変数を使おう(6)', + variable7: '変数を使おう(7)', + variable8: '変数を使おう(8)', + variable9: '変数を使おう(9)', + variable10: '変数を使おう(10)', while1: 'while文を使おう(1)', while2: 'while文を使おう(2)', for1: 'for文を使おう(1)', @@ -108,8 +138,34 @@ export const problemIdToName: Record = { export const courseIdToLectureIndexToProblemIds: Record = { tuBeginner1: [ - ['straight', 'stepBack', 'turnRight', 'turnRightAndTurnLeft'], - ['square1', 'square2', 'variable', 'variable2', 'variable3'], + [ + 'straight', + 'straight2', + 'stepBack', + 'stepBack2', + 'turnRight', + 'turnRight2', + 'turnLeftAndRight', + 'turnLeftAndRight2', + 'turnLeftAndRight3', + 'turnLeftAndRight4', + ], + [ + 'square1', + 'square2', + 'square3', + 'square4', + 'variable', + 'variable2', + 'variable3', + 'variable4', + 'variable5', + 'variable6', + 'variable7', + 'variable8', + 'variable9', + 'variable10', + ], ['while1', 'while2', 'for1', 'for2', 'for3'], ['doubleLoop1', 'doubleLoop2', 'if1', 'if2'], ['elseIf1', 'elseIf2', 'switch1', 'switch2'], @@ -138,6 +194,24 @@ public class Main { 亀.前に進む(); // sid 亀.前に進む(); // sid } +} + `.trim(), + }, + straight2: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + } } `.trim(), }, @@ -154,6 +228,28 @@ public class Main { 亀.前に進む(); // sid 亀.後に戻る(); // sid } +} + `.trim(), + }, + stepBack2: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').backward(); +s.get('亀').forward(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.後に戻る(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + } } `.trim(), }, @@ -175,12 +271,78 @@ public class Main { } `.trim(), }, - turnRightAndTurnLeft: { + turnRight2: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + turnLeftAndRight: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').turnLeft(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.左を向く(); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + turnLeftAndRight2: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').forward(); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').turnLeft(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.左を向く(); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + turnLeftAndRight3: { instrumented: ` s.set('亀', new Turtle()); s.get('亀').turnRight(); s.get('亀').forward(); s.get('亀').turnLeft(); +s.get('亀').forward(); +s.get('亀').turnRight(); s.get('亀').forward(); `.trim(), java: ` @@ -191,6 +353,36 @@ public class Main { 亀.前に進む(); // sid 亀.左を向く(); // sid 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + turnLeftAndRight4: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').turnLeft(); +s.get('亀').forward(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.左を向く(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid } } `.trim(), @@ -239,6 +431,67 @@ public class Main { } `.trim(), }, + square3: { + instrumented: ` +s.set('亀', new Turtle(<2-5>, <2-5>)); +s.get('亀').forward(); +s.get('亀').turnLeft(); +s.get('亀').forward(); +s.get('亀').turnLeft(); +s.get('亀').forward(); +s.get('亀').turnLeft(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(<2-5>, <2-5>); // sid + 亀.前に進む(); // sid + 亀.左を向く(); // sid + 亀.前に進む(); // sid + 亀.左を向く(); // sid + 亀.前に進む(); // sid + 亀.左を向く(); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + square4: { + instrumented: ` +s.set('亀', new Turtle()); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').forward(); +s.get('亀').turnRight(); +s.get('亀').forward(); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + Turtle 亀 = new Turtle(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + 亀.右を向く(); // sid + 亀.前に進む(); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + variable: { instrumented: ` s.set('x', <1-5>); @@ -257,6 +510,24 @@ public class Main { }, variable2: { instrumented: ` +s.set('y', <2-6>); +s.set('y', s.get('y') - 1); +s.set('亀', new Turtle(<1-5>, s.get('y'))); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int y = <2-6>; // sid + y = y - 1; // sid + Turtle 亀 = new Turtle(<1-5>, y); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + variable3: { + instrumented: ` s.set('x', <1-4>); s.set('x', s.get('x') + 1); s.set('y', s.get('x') + 1); @@ -275,12 +546,32 @@ public class Main { } `.trim(), }, - variable3: { + variable4: { + instrumented: ` +s.set('y', <1-4>); +s.set('y', s.get('y') + 1); +s.set('x', s.get('y') - 2); +s.set('亀', new Turtle(s.get('x'), s.get('y'))); +s.get('亀').forward(); +`.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int y = <1-4>; // sid + y = y + 1; // sid + int x = y - 2; // sid + Turtle 亀 = new Turtle(x, y); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + variable5: { instrumented: ` s.set('x', <1-5>); s.set('x', s.get('x') - 1); s.set('y', s.get('x') * 2); -s.set('y', Math.floor(s.get('y') / 3)); +s.set('y', s.get('y') / 3); s.set('亀', new Turtle(s.get('x'), s.get('y'))); s.get('亀').forward(); `.trim(), @@ -294,6 +585,122 @@ public class Main { Turtle 亀 = new Turtle(x, y); // sid 亀.前に進む(); // sid } +} + `.trim(), + }, + variable6: { + instrumented: ` +s.set('a', <1-3>); +s.set('b', s.get('a') * 2); +s.set('c', s.get('b') - 2); +s.set('亀', new Turtle(s.get('c'), s.get('b'))); +s.get('亀').forward(); +`.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int a = <1-3>; // sid + int b = a * 2; // sid + int c = b - 2; // sid + Turtle 亀 = new Turtle(c, b); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + variable7: { + instrumented: ` +s.set('x', <0-2>); +s.set('y', (s.get('x') * 2) + 1); +s.set('z', (s.get('y') * 2) + (s.get('x') / 2)); +s.set('x', s.get('z') / 3); +s.set('亀', new Turtle(s.get('x'), s.get('y'))); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int x = <0-2>; // sid + int y = (x * 2) + 1; // sid + int z = (y * 2) + (x / 2); // sid + x = z / 3; // sid + Turtle 亀 = new Turtle(x, y); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + variable8: { + instrumented: ` +s.set('x', <0-2>); +s.set('y', (s.get('x') * 3) + 2); +s.set('z', (s.get('y') * 2) - (s.get('x') * 3)); +s.set('x', (s.get('z') / 4) % 7); +s.set('y', (s.get('x') + s.get('y')) % 7); +s.set('亀', new Turtle(s.get('x'), s.get('y'))); +s.get('亀').backward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int x = <0-2>; // sid + int y = (x * 3) + 2; // sid + int z = (y * 2) - (x * 3); // sid + x = (z / 4) % 7; // sid + y = (x + y) % 7; // sid + Turtle 亀 = new Turtle(x, y); // sid + 亀.後に戻る(); // sid + } +} + `.trim(), + }, + variable9: { + instrumented: ` +s.set('x', <0-3>); +s.set('y', (s.get('x') * 4) + 3); +s.set('z', (s.get('y') * 3) - (s.get('x') * 2)); +s.set('x', ((s.get('z') / 5) + s.get('x')) % 7); +s.set('y', ((s.get('x') * 2) + s.get('y')) % 7); +s.set('亀', new Turtle(s.get('x'), s.get('y'))); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int x = <0-3>; // sid + int y = (x * 4) + 3; // sid + int z = (y * 3) - (x * 2); // sid + x = ((z / 5) + x) % 7; // sid + y = ((x * 2) + y) % 7; // sid + Turtle 亀 = new Turtle(x, y); // sid + 亀.前に進む(); // sid + } +} + `.trim(), + }, + variable10: { + instrumented: ` +s.set('x', <0-3>); +s.set('y', (s.get('x') * 5) + 4); +s.set('z', (s.get('y') * 2) - (s.get('x') * 3)); +s.set('w', (s.get('z') + s.get('x')) % 5); +s.set('x', ((s.get('z') / 6) + s.get('w')) % 7); +s.set('y', ((s.get('x') * 3) + s.get('y')) % 7); +s.set('亀', new Turtle(s.get('x'), s.get('y'))); +s.get('亀').forward(); + `.trim(), + java: ` +public class Main { + public static void main(String[] args) { + int x = <0-3>; // sid + int y = (x * 5) + 4; // sid + int z = (y * 2) - (x * 3); // sid + int w = (z + x) % 5; // sid + x = ((z / 6) + w) % 7; // sid + y = ((x * 3) + y) % 7; // sid + Turtle 亀 = new Turtle(x, y); // sid + 亀.前に進む(); // sid + } } `.trim(), }, @@ -391,7 +798,7 @@ s.set('x', 0); for (s.set('i', 2); s.get('i') <= <4-5>; s.set('i', s.get('i') + 1)) { s.set('x', s.get('x') + s.get('i')); } -s.set('x', Math.floor(s.get('x') / 3)); +s.set('x', s.get('x') / 3); s.set('亀', new Turtle(s.get('x'), 0)); s.get('亀').forward(); `.trim(), diff --git a/src/problems/traceProgram.ts b/src/problems/traceProgram.ts index d55bab55..7bdb2cd7 100644 --- a/src/problems/traceProgram.ts +++ b/src/problems/traceProgram.ts @@ -89,7 +89,7 @@ class Scope { throw new Error(); } set(varName, value, sid) { - this.vars[varName] = value; + this.vars[varName] = typeof value === 'number' ? Math.floor(value) : value; addTrace(sid); } enterNewScope(params) { diff --git a/tests/unit/problemData.test.ts b/tests/unit/problemData.test.ts index 83e896a8..4ce0992b 100644 --- a/tests/unit/problemData.test.ts +++ b/tests/unit/problemData.test.ts @@ -4,5 +4,7 @@ import { generateProblem } from '../../src/problems/generateProblem'; import { problemIdToLanguageIdToProgram } from '../../src/problems/problemData'; test.each(Object.keys(problemIdToLanguageIdToProgram))('Trace the program of %s', (problemId) => { - expect(generateProblem(problemId, 'java', Date.now().toString())).not.toBeFalsy(); + for (let i = 0; i < 100; i++) { + expect(generateProblem(problemId, 'java', Date.now().toString())).not.toBeFalsy(); + } }); diff --git a/tests/unit/traceCode.test.ts b/tests/unit/traceProgram.test.ts similarity index 100% rename from tests/unit/traceCode.test.ts rename to tests/unit/traceProgram.test.ts