From 05f47bb19cd1d2758c786e1547a2ac55f216ffea Mon Sep 17 00:00:00 2001 From: Conner Mo Date: Fri, 6 Jun 2025 21:15:59 +0800 Subject: [PATCH] feat: improve translation system and add Chinese support - Refactor translation system for better language support - Add dynamic language support through add_language method - Update translation rules to be more teaching-focused - Add Chinese translation support - Update test files and compiled translations --- .gitignore | 1 + tests/golden_files/zh/test_transcript.json | 2156 +++++++++-------- .../locales/zh/LC_MESSAGES/futurecoder.mo | Bin 103009 -> 299032 bytes translations/translate_futurecoder.py | 983 ++++++++ 4 files changed, 2071 insertions(+), 1069 deletions(-) create mode 100644 translations/translate_futurecoder.py diff --git a/.gitignore b/.gitignore index 659cf51c..7b6cfdd7 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,4 @@ homepage/static/css/**/*.css translations/codes.json .DS_Store +translations/chunks/ diff --git a/tests/golden_files/zh/test_transcript.json b/tests/golden_files/zh/test_transcript.json index e032ca5d..1ebbd701 100644 --- a/tests/golden_files/zh/test_transcript.json +++ b/tests/golden_files/zh/test_transcript.json @@ -1,11 +1,11 @@ [ { - "page": "Introducing The Shell", + "page": "\u4ecb\u7ecd Shell", "program": [ "'literally anything'" ], "response": { - "message": "

Awesome, you're trying out your own experiments!\nThat's a great sign. Keep it up.\nJust letting you know that you do need to eventually type 1+2 for the book to move forward.

", + "message": "

\u5f88\u68d2\uff0c\u4f60\u5728\u5c1d\u8bd5\u81ea\u5df1\u7684\u5b9e\u9a8c\uff01\n\u8fd9\u771f\u662f\u4e2a\u597d\u5146\u5934\u3002\u7ee7\u7eed\u4fdd\u6301\u3002\n\u53ea\u662f\u8ba9\u4f60\u77e5\u9053\uff0c\u4f60\u6700\u7ec8\u9700\u8981\u8f93\u5165 1+2 \u624d\u80fd\u7ee7\u7eed\u8fdb\u884c\u3002

", "passed": false, "result": [ { @@ -17,12 +17,12 @@ "step": "first_expression" }, { - "page": "Introducing The Shell", + "get_solution": "program", + "page": "\u4ecb\u7ecd Shell", "program": [ "1+2" ], "response": { - "message": "", "passed": true, "result": [ { @@ -34,16 +34,17 @@ "step": "first_expression" }, { - "page": "Introducing The Shell", + "page": "\u4ecb\u7ecd Shell", "program": [ "3 x 4" ], "response": { - "message": "

I see an 'x'. If you're trying to multiply, use an asterisk, e.g:

\n
3 * 4\n
", + "message": "

\u6211\u770b\u5230\u4e00\u4e2a 'x'\u3002\u5982\u679c\u4f60\u60f3\u8981\u4e58\u6cd5\uff0c\u8bf7\u4f7f\u7528\u661f\u53f7\uff0c\u4f8b\u5982\uff1a

\n
3 * 4\n
", "passed": false, "result": [ { - "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nCurrently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.\n\nUnless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/aroberge/friendly/issues\n\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

Currently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.

\n

Unless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/friendly-traceback/friendly-traceback/issues

", + "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\n\u5728\u884c 1\n", "type": "syntax_error" } ] @@ -51,12 +52,12 @@ "step": "more_calculation" }, { - "page": "Introducing The Shell", + "get_solution": "program", + "page": "\u4ecb\u7ecd Shell", "program": [ "5 - 6" ], "response": { - "message": "", "passed": true, "result": [ { @@ -68,12 +69,12 @@ "step": "more_calculation" }, { - "page": "Introducing Strings", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u7b26\u4e32", "program": [ "'hello'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -85,12 +86,12 @@ "step": "hello_string" }, { - "page": "Adding Strings", + "get_solution": "program", + "page": "\u6dfb\u52a0\u5b57\u7b26\u4e32", "program": [ "'hello' + 'world'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -102,12 +103,12 @@ "step": "hello_world_concat" }, { - "page": "Adding Strings", + "page": "\u6dfb\u52a0\u5b57\u7b26\u4e32", "program": [ "'hello world'" ], "response": { - "message": "

You must still add two or more strings together.

", + "message": "

\u4f60\u4ecd\u7136\u5fc5\u987b\u5c06\u4e24\u4e2a\u6216\u66f4\u591a\u5b57\u7b26\u4e32\u76f8\u52a0\u3002

", "passed": false, "result": [ { @@ -119,15 +120,12 @@ "step": "hello_world_space" }, { - "get_solution": [ - "'hello ' + 'world'" - ], - "page": "Adding Strings", + "get_solution": "program", + "page": "\u6dfb\u52a0\u5b57\u7b26\u4e32", "program": [ "'hello ' + 'world'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -139,36 +137,36 @@ "step": "hello_world_space" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "word = 'Hello'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "word_assign" }, { - "page": "Introducing Variables", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "word = 2" ], "response": { - "message": "

Oops, you need to set word = 'Hello' before we can continue.

", + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e word = 'Hello'\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", "passed": false, "result": [] }, "step": "word_check" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "word" ], "response": { - "message": "", "passed": true, "result": [ { @@ -180,12 +178,12 @@ "step": "word_check" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "'word'" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "'word'", @@ -194,7 +192,7 @@ "'word'", "Hello", "'Hello'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -207,21 +205,21 @@ "step": "word_string_check" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "sunshine" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "sunshine", "'sunshine'", "Hello", "'Hello'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -235,11 +233,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "sunshine", "is_current": true, "lineno": 1, + "text": "sunshine", "type": "line" } ], @@ -254,7 +254,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | sunshine", " ^^^^^^^^", "", @@ -267,72 +267,72 @@ "step": "sunshine_undefined_check" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "foo = 3" ], "response": { - "message": "

Put your_name before the = to create a variable called your_name.

", + "message": "

\u5728 = \u524d\u9762\u653e\u4e0a your_name \u6765\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a your_name \u7684\u53d8\u91cf\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = ''" ], "response": { - "message": "

For this exercise, choose a non-empty string

", + "message": "

\u5bf9\u4e8e\u8fd9\u4e2a\u7ec3\u4e60\uff0c\u9009\u62e9\u4e00\u4e2a\u975e\u7a7a\u5b57\u7b26\u4e32\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = 3" ], "response": { - "message": "

You've got the your_name = part right, now put a string (use quotes) on the right of the =.

", + "message": "

\u4f60\u5df2\u7ecf\u628a your_name = \u90e8\u5206\u5199\u5bf9\u4e86\uff0c\u73b0\u5728\u5728 = \u7684\u53f3\u8fb9\u653e\u4e00\u4e2a\u5b57\u7b26\u4e32\uff08\u4f7f\u7528\u5f15\u53f7\uff09\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = ' Alex'" ], "response": { - "message": "

For this exercise, choose a name that doesn't start with a space.

", + "message": "

\u5bf9\u4e8e\u8fd9\u4e2a\u7ec3\u4e60\uff0c\u9009\u62e9\u4e00\u4e2a\u4e0d\u4ee5\u7a7a\u683c\u5f00\u5934\u7684\u540d\u5b57\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = 'Alex'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "'Hello ' + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -344,24 +344,24 @@ "step": "hello_plus_name" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word = 2" ], "response": { - "message": "

Oops, you need to set word = 'Hello' before we can continue.

", + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e word = 'Hello'\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", "passed": false, "result": [] }, "step": "word_plus_name" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -373,27 +373,24 @@ "step": "word_plus_name" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word = 2" ], "response": { - "message": "

Oops, you need to set word = 'Hello' before we can continue.

", + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e word = 'Hello'\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", "passed": false, "result": [] }, "step": "word_plus_name_with_space" }, { - "get_solution": [ - "word + ' ' + your_name" - ], - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word + ' ' + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -405,24 +402,24 @@ "step": "word_plus_name_with_space" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word = 'Goodbye'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "word_assign_goodbye" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word + ' ' + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -434,12 +431,12 @@ "step": "goodbye_plus_name" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "print(word + ' ' + your_name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -451,7 +448,8 @@ "step": "first_print" }, { - "page": "Writing Programs", + "get_solution": "program", + "page": "\u7f16\u5199\u7a0b\u5e8f", "program": [ "word = 'Hello'", "name = 'World'", @@ -460,7 +458,6 @@ "print(word + ' ' + name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -472,7 +469,8 @@ "step": "editor_hello_world" }, { - "page": "Storing Calculations In Variables", + "get_solution": "program", + "page": "\u5728\u53d8\u91cf\u4e2d\u5b58\u50a8\u8ba1\u7b97", "program": [ "word = 'Hello'", "name = 'World'", @@ -480,7 +478,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World", @@ -491,7 +488,7 @@ "'Hello' + ' ' + 'World'", "Hello World", "'Hello World'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -504,7 +501,8 @@ "step": "sentence_equals_word_plus_name" }, { - "page": "Storing Calculations In Variables", + "get_solution": "program", + "page": "\u5728\u53d8\u91cf\u4e2d\u5b58\u50a8\u8ba1\u7b97", "program": [ "word = 'Hello'", "name = 'World'", @@ -514,7 +512,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World\nHello World", @@ -522,7 +519,7 @@ "Hello World\nHello World", "Hello World\nGoodbye World", "Goodbye World\nGoodbye World", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -535,13 +532,13 @@ "step": "sentence_doesnt_change" }, { - "page": "Introducing For Loops", + "get_solution": "program", + "page": "\u5f15\u5165 For \u5faa\u73af", "program": [ "name = 'World'", "for character in name: print(character)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -553,17 +550,18 @@ "step": "first_for_loop" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "for character in name:", "print(character)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print(character)\n ^\nIndentationError: expected an indented block\nat line 2\n\nAn `IndentationError` occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.\n\nLine `2` identified above was expected to begin a new indented block.\n\n\n", + "friendly": "

An IndentationError occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.

\n

Line 2 identified above was expected to begin a new indented block.

", + "text": " print(character)\n ^^^^^\nIndentationError: expected an indented block after 'for' statement on line 1\n\u5728\u884c 2\n", "type": "syntax_error" } ] @@ -571,7 +569,8 @@ "step": "missing_indentation" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "name = 'World'", "", @@ -580,7 +579,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -592,7 +590,8 @@ "step": "two_indented_lines" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "name = 'World'", "", @@ -601,7 +600,6 @@ "print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -613,18 +611,19 @@ "step": "one_indented_line" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "for character in name:", " print(character)", " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print('---')\n ^\nIndentationError: unindent does not match any outer indentation level\nat line 3\n\nAn `IndentationError` occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.\n\nLine `3` identified above is less indented than expected.\n\n\n", + "friendly": "

An IndentationError occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.

\n

Line 3 identified above is less indented than expected.

", + "text": " print('---')\n ^\nIndentationError: unindent does not match any outer indentation level\n\u5728\u884c 3\n", "type": "syntax_error" } ] @@ -636,14 +635,13 @@ "for character in name:", " print('---' + character)" ], - "page": "Basic For Loop Exercises", + "page": "\u57fa\u672c\u7684 for \u5faa\u73af\u7ec3\u4e60", "program": [ "name = 'World'", "for character in name:", " print('---' + character)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -659,14 +657,13 @@ "for _ in name:", " print(name)" ], - "page": "Basic For Loop Exercises", + "page": "\u57fa\u672c\u7684 for \u5faa\u73af\u7ec3\u4e60", "program": [ "name = 'World'", "for _ in name:", " print(name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -678,7 +675,8 @@ "step": "loop_exercise_2" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "hello = 'Hello'", "print(hello)", @@ -686,7 +684,6 @@ "print(hello)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello\nHello!", @@ -694,7 +691,7 @@ "Hello\nHello", "Hello\nHello!", "Hello!\nHello!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -707,7 +704,8 @@ "step": "hello_plus_equals" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "name = 'World'", "line = '-'", @@ -716,7 +714,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "-W\n-Wo\n-Wor\n-Worl\n-World", @@ -729,7 +726,7 @@ "-World\n-Worl\n-Wor\n-Wo\n-W", "-World\n-World\n-World\n-World\n-World", "-World\n--World\n---World\n----World\n-----World", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -742,7 +739,8 @@ "step": "name_triangle" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "name = 'World'", "line = '-'", @@ -751,7 +749,6 @@ " line = line + char" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "-\n-W\n-Wo\n-Wor\n-Worl", @@ -759,7 +756,7 @@ "-W\n-Wo\n-Wor\n-Worl\n-World", "-Wo\n-Wor\n-Worl\n-World", "-\n-W\n-Wo\n-Wor\n-Worl", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -772,12 +769,12 @@ "step": "name_triangle_missing_last_line" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "'' + '' + ''" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "''", @@ -791,7 +788,7 @@ "'' '' ''", "' '' '' '", "++", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -810,7 +807,7 @@ " line = line + char", " print(line)" ], - "page": "Building Up Strings", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "name = 'World'", "line = ''", @@ -819,7 +816,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -837,7 +833,7 @@ " line = line + char + ' '", " print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -846,7 +842,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -864,7 +859,7 @@ " line = char + line", " print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -873,7 +868,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -892,7 +886,7 @@ "print(name)", "print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -902,7 +896,6 @@ "print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -923,7 +916,7 @@ "print('|' + name + '|')", "print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -935,7 +928,6 @@ "print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -958,7 +950,7 @@ " print(char + spaces + char)", "print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = '+' + name + '+'", @@ -972,7 +964,6 @@ "print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -984,7 +975,7 @@ "step": "name_box_2" }, { - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "spaces = ''", @@ -993,7 +984,7 @@ " print(spaces + char)" ], "response": { - "message": "

Almost there! You have one space too many before each letter.\nMake sure that the first time your loop calls print\nyour variable which will contain the spaces is an empty string.\nCheck the order of your code.

", + "message": "

\u5feb\u5230\u4e86\uff01\u6bcf\u4e2a\u5b57\u6bcd\u524d\u9762\u591a\u4e86\u4e00\u4e2a\u7a7a\u683c\u3002\n\u786e\u4fdd\u4f60\u7684\u5faa\u73af\u7b2c\u4e00\u6b21\u8c03\u7528 print\n\u65f6\uff0c\u5305\u542b\u7a7a\u683c\u7684\u53d8\u91cf\u662f\u4e00\u4e2a\u7a7a\u5b57\u7b26\u4e32\u3002\n\u68c0\u67e5\u4f60\u7684\u4ee3\u7801\u987a\u5e8f\u3002

", "passed": false, "result": [ { @@ -1011,7 +1002,7 @@ " print(spaces + char)", " spaces += ' '" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "spaces = ''", @@ -1020,7 +1011,6 @@ " spaces += ' '" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1032,7 +1022,8 @@ "step": "diagonal_name_bonus_challenge" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd If \u8bed\u53e5", "program": [ "condition = True", "print(condition)", @@ -1040,7 +1031,6 @@ "print(condition)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1052,7 +1042,8 @@ "step": "introducing_booleans" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd If \u8bed\u53e5", "program": [ "if True:", " print('This gets printed')", @@ -1061,7 +1052,6 @@ " print('This does not')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1073,7 +1063,8 @@ "step": "first_if_statements" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd If \u8bed\u53e5", "program": [ "sentence = 'Hello World'", "excited = True", @@ -1082,14 +1073,13 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World!", "choices": [ "Hello World", "Hello World!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1102,7 +1092,8 @@ "step": "excited_example" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd If \u8bed\u53e5", "program": [ "sentence = 'Hello World'", "excited = False", @@ -1111,14 +1102,13 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World", "choices": [ "Hello World", "Hello World!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1138,7 +1128,7 @@ " sentence += '?'", "print(sentence)" ], - "page": "Introducing If Statements", + "page": "\u4ecb\u7ecd If \u8bed\u53e5", "program": [ "sentence = 'Hello'", "excited = True", @@ -1150,7 +1140,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1162,7 +1151,8 @@ "step": "excited_confused_exercise" }, { - "page": "Combining Compound Statements", + "get_solution": "program", + "page": "\u7ec4\u5408\u590d\u5408\u8bed\u53e5", "program": [ "sentence = 'Hello World'", "excited = True", @@ -1176,7 +1166,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "H!e!l!l!o! !W!o!r!l!d!", @@ -1190,7 +1179,7 @@ "!Hello World!", "H!e!l!l!o! !W!o!r!l!d!", "!H!e!l!l!o! !W!o!r!l!d", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1203,7 +1192,8 @@ "step": "for_inside_if" }, { - "page": "Understanding Programs With snoop", + "get_solution": "program", + "page": "\u4f7f\u7528 snoop \u7406\u89e3\u7a0b\u5e8f", "program": [ "sentence = 'Hello World'", "", @@ -1217,7 +1207,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "ello World", @@ -1227,7 +1216,7 @@ "Hello Worl", "H", "d", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1240,7 +1229,8 @@ "step": "print_tail" }, { - "page": "Understanding Programs With snoop", + "get_solution": "program", + "page": "\u4f7f\u7528 snoop \u7406\u89e3\u7a0b\u5e8f", "program": [ "sentence = 'Hello World'", "", @@ -1254,208 +1244,43 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 4\u001b[0m | new_sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 4\u001b[0m | new_sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 10\u001b[0m | print(new_sentence)\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "ello World", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 10\u001b[0m | print(new_sentence)\n", + "text": "\n", "type": "stdout" }, { - "text": "ello World\n", - "type": "stdout" + "text": "", + "type": "snoop" } ] }, @@ -1472,7 +1297,7 @@ "", "print(new_sentence)" ], - "page": "Understanding Programs With snoop", + "page": "\u4f7f\u7528 snoop \u7406\u89e3\u7a0b\u5e8f", "program": [ "sentence = 'Hello there'", "include = True", @@ -1485,7 +1310,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1497,7 +1321,8 @@ "step": "print_first_character" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "condition = True", "if condition:", @@ -1506,7 +1331,6 @@ " print('No')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1518,7 +1342,8 @@ "step": "first_if_else" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "condition = False", "if condition:", @@ -1527,7 +1352,6 @@ " print('No')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1539,7 +1363,8 @@ "step": "first_if_else_false" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "sentence = 'Hello World'", "excited = True", @@ -1550,7 +1375,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1562,7 +1386,8 @@ "step": "if_upper_else_lower" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "sentence = 'Hello World'", "excited = False", @@ -1573,7 +1398,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1585,7 +1409,8 @@ "step": "if_upper_else_lower_false" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "sentence = 'Hello World'", "excited = False", @@ -1597,14 +1422,13 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "Hello World", "Hello World!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1620,11 +1444,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 6, "lines": [ { - "content": "sentence += char", "is_current": true, "lineno": 6, + "text": "sentence += char", "type": "line" } ], @@ -1648,7 +1474,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 6, in ", + " File \"/my_program.py\", line 6, in ", " 5 | char = '!'", "--> 6 | sentence += char", " ^^^^", @@ -1664,7 +1490,16 @@ "step": "undefined_char" }, { - "page": "if and else", + "get_solution": [ + "if excited:", + " char = '!'", + "else:", + " char = '.'", + "sentence += char", + "", + "print(sentence)" + ], + "page": "if \u548c else", "program": [ "sentence = 'Hello there'", "excited = True", @@ -1677,7 +1512,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1702,7 +1536,7 @@ "", "print(new_sentence)" ], - "page": "if and else", + "page": "if \u548c else", "program": [ "sentence = 'HELLO THERE'", "upper = True", @@ -1718,7 +1552,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1744,7 +1577,7 @@ "", "print(new_sentence)" ], - "page": "if and else", + "page": "if \u548c else", "program": [ "sentence = 'One more exercise, and then you can relax.'", "upper = True", @@ -1761,7 +1594,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1773,14 +1605,14 @@ "step": "spongebob" }, { - "page": "The Equality Operator", + "get_solution": "program", + "page": "\u7b49\u53f7\u8fd0\u7b97\u7b26", "program": [ "print(1 + 2 == 3)", "print(4 + 5 == 6)", "print('ab' + 'c' == 'a' + 'bc')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1792,16 +1624,17 @@ "step": "introducing_equality" }, { - "page": "The Equality Operator", + "get_solution": "program", + "page": "\u7b49\u53f7\u8fd0\u7b97\u7b26", "program": [ "print(1 + 2 = 3)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print(1 + 2 = 3)\n ^\nSyntaxError: expression cannot contain assignment, perhaps you meant \"==\"?\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nYou likely called a function with a named argument:\n\n a_function(invalid=something) \n\nwhere `invalid` is not a valid variable name in Python\neither because it starts with a number, or is a string,\nor contains a period, etc.\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You likely called a function with a named argument:

\n
a_function(invalid=something)\n
\n

where invalid is not a valid variable name in Python\neither because it starts with a number, or is a string,\nor contains a period, etc.

", + "text": " print(1 + 2 = 3)\n ^^^^^^^\nSyntaxError: expression cannot contain assignment, perhaps you meant \"==\"?\n\u5728\u884c 1\n", "type": "syntax_error" } ] @@ -1809,7 +1642,8 @@ "step": "equality_vs_assignment" }, { - "page": "The Equality Operator", + "get_solution": "program", + "page": "\u7b49\u53f7\u8fd0\u7b97\u7b26", "program": [ "name = 'kesha'", "new_name = ''", @@ -1821,7 +1655,6 @@ "print(new_name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1846,7 +1679,7 @@ "", "print(new_name)" ], - "page": "The Equality Operator", + "page": "\u7b49\u53f7\u8fd0\u7b97\u7b26", "program": [ "name = 'kesha'", "new_name = ''", @@ -1862,7 +1695,6 @@ "print(new_name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1874,7 +1706,8 @@ "step": "if_equals_replacing_characters_exercise" }, { - "page": "Introducing elif", + "get_solution": "program", + "page": "\u4ecb\u7ecdelif", "program": [ "dna = 'AGTAGCGTC'", "opposite_dna = ''", @@ -1892,7 +1725,6 @@ "print(opposite_dna)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1921,7 +1753,7 @@ "", "print(opposite_dna)" ], - "page": "Introducing elif", + "page": "\u4ecb\u7ecdelif", "program": [ "dna = 'AGTAGCGTCCTTAGTTACAGGATGGCTTAT'", "opposite_dna = ''", @@ -1941,7 +1773,6 @@ "print(opposite_dna)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1953,7 +1784,8 @@ "step": "dna_example_with_else" }, { - "page": "Introducing elif", + "get_solution": "program", + "page": "\u4ecb\u7ecdelif", "program": [ "dna = 'AGTAGCGTC'", "opposite_dna = ''", @@ -1971,7 +1803,6 @@ "print(opposite_dna)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1983,13 +1814,21 @@ "step": "dna_example_with_elif" }, { - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "1 != 2" ], "response": { - "message": "", "passed": true, + "prediction": { + "answer": "True", + "choices": [ + "True", + "False", + "\u9519\u8bef" + ] + }, "result": [ { "text": "True\n", @@ -2000,7 +1839,8 @@ "step": "try_not_equals" }, { - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "sentence = 'The e key on my keyboard is broken'", "new_sentence = ''", @@ -2010,7 +1850,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2022,15 +1861,12 @@ "step": "brokn_kyboard" }, { - "get_solution": [ - "1 < 2" - ], - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "1 < 2" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2042,15 +1878,12 @@ "step": "introducing_less_than" }, { - "get_solution": [ - "'1' < '2'" - ], - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "'1' < '2'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2062,7 +1895,8 @@ "step": "comparing_strings" }, { - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "percentage = 73", "", @@ -2078,7 +1912,6 @@ "print(grade)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "B", @@ -2087,7 +1920,7 @@ "C", "B", "A", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2113,7 +1946,7 @@ " first = x3", "print(first)" ], - "page": "Other Comparison Operators", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "x1 = 1", "x2 = 2", @@ -2131,7 +1964,6 @@ "print(first)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2143,7 +1975,8 @@ "step": "min_three_exercise" }, { - "page": "Introducing Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "words = ['This', 'is', 'a', 'list']", "", @@ -2151,7 +1984,6 @@ " print(word)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2163,14 +1995,14 @@ "step": "first_list" }, { - "page": "Introducing Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "x = 1", "things = ['Hello', x, x + 3]", "print(things)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2182,7 +2014,8 @@ "step": "can_contain_anything" }, { - "page": "Introducing Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "numbers = [3, 1, 4, 1, 5, 9]", "", @@ -2193,7 +2026,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2212,7 +2044,7 @@ "", "print(total)" ], - "page": "Introducing Lists", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "words = ['This', 'is', 'a', 'list']", "total = ''", @@ -2222,7 +2054,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2246,7 +2077,7 @@ "", "print(total)" ], - "page": "Introducing Lists", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "words = ['This', 'is', 'a', 'list']", "separator = ' - '", @@ -2262,7 +2093,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2280,7 +2110,7 @@ " double += [number * 2]", "print(double)" ], - "page": "Building New Lists", + "page": "\u6784\u5efa\u65b0\u5217\u8868", "program": [ "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]", "double = []", @@ -2289,7 +2119,6 @@ "print(double)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2308,7 +2137,7 @@ " big_numbers.append(number)", "print(big_numbers)" ], - "page": "Building New Lists", + "page": "\u6784\u5efa\u65b0\u5217\u8868", "program": [ "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]", "big_numbers = []", @@ -2318,7 +2147,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2338,7 +2166,7 @@ "", "print(found)" ], - "page": "Using break to end a loop early", + "page": "\u4f7f\u7528 break \u63d0\u524d\u7ed3\u675f\u5faa\u73af", "program": [ "things = ['This', 'is', 'a', 'list']", "thing_to_find = 'is'", @@ -2350,7 +2178,6 @@ "print(found)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2362,7 +2189,8 @@ "step": "list_contains_exercise" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "", @@ -2372,7 +2200,6 @@ "print(words[3])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2384,12 +2211,12 @@ "step": "introducing_subscripting" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words[4]" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2402,11 +2229,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "words[4]", "is_current": true, "lineno": 1, + "text": "words[4]", "type": "line" } ], @@ -2426,7 +2255,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | words[4]", " ^^^^^^^^", "words = ['This', 'is', 'a', 'list']", @@ -2440,7 +2269,8 @@ "step": "index_error" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "indices = [0, 1, 2, 3]", @@ -2450,7 +2280,6 @@ " print(words[index])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "0\nThis\n1\nis\n2\na\n3\nlist", @@ -2461,7 +2290,7 @@ "This\n0\nis\n1\na\n2\nlist\n3", "0\n1\n2\n3\nThis\nis\na\nlist", "This\nis\na\nlist\n0\n1\n2\n3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2474,7 +2303,8 @@ "step": "introducing_len_and_range" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "indices = range(4)", @@ -2484,7 +2314,6 @@ " print(words[index])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2496,7 +2325,8 @@ "step": "range_len" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "indices = range(4)", "", @@ -2506,7 +2336,6 @@ "print(indices[3])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "0\n1\n2\n3", @@ -2516,7 +2345,7 @@ "[0]\n[1]\n[2]\n[3]", "[1]\n[2]\n[3]\n[4]", "This\nis\na\nlist", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2529,22 +2358,22 @@ "step": "printing_the_range" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "indices[4]" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "0", "1", "2", "3", "4", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2558,11 +2387,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "indices[4]", "is_current": true, "lineno": 1, + "text": "indices[4]", "type": "line" } ], @@ -2576,13 +2407,13 @@ ] } ], - "friendly": "

An IndexError occurs when you try to get an item from a list,\na tuple, or a similar object (sequence), and use an index which\ndoes not exist; typically, this happens because the index you give\nis greater than the length of the sequence.

\n

You have tried to get the item with index 4 of indices,\nrange object of length 4.\nThe valid index values of indices are integers ranging from\n-4 to 3.

", + "friendly": "

An IndexError occurs when you try to get an item from a list,\na tuple, or a similar object (sequence), and use an index which\ndoes not exist; typically, this happens because the index you give\nis greater than the length of the sequence.

\n

You have tried to get the item with index 4 of indices,\nrange object of length 4.\nThe valid index values of indices are integers ranging from\n-4 to 3.

", "tail": "" } ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | indices[4]", " ^^^^^^^^^^", "indices = range(0, 4)", @@ -2596,12 +2427,12 @@ "step": "indices_out_of_bounds" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "range(4)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2613,12 +2444,12 @@ "step": "range_almost_the_same_as_list" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "list(range(4))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[0, 1, 2, 3]", @@ -2630,7 +2461,7 @@ "range(0, 1, 2, 3)", "(0, 1, 2, 3)", "[0, 1, 2, 3]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2643,13 +2474,13 @@ "step": "range_versus_list" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "print(len(words))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "4", @@ -2660,7 +2491,7 @@ "3", "4", "5", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2676,13 +2507,12 @@ "get_solution": [ "print(words[len(words) - 1])" ], - "page": "Getting elements at a position, range(), and len()", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['Python']", "print(words[len(words) - 1])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2699,7 +2529,7 @@ " print(index)", " print(words[index])" ], - "page": "Getting elements at a position, range(), and len()", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['Python']", "for index in range(len(words)):", @@ -2707,7 +2537,6 @@ " print(words[index])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2719,7 +2548,7 @@ "step": "print_indices_and_words" }, { - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "things = ['on', 'the', 'way', 'to', 'the', 'store']", "to_find = 'the'", @@ -2728,7 +2557,7 @@ " print(i)" ], "response": { - "message": "

You're almost there! However, this prints all the indices,\nnot just the first one.

", + "message": "

\u4f60\u5feb\u5230\u4e86\uff01\u4f46\u662f\uff0c\u8fd9\u4f1a\u6253\u5370\u6240\u6709\u7684\u7d22\u5f15\uff0c\n\u800c\u4e0d\u4ec5\u4ec5\u662f\u7b2c\u4e00\u4e2a\u3002

", "passed": false, "result": [ { @@ -2740,7 +2569,7 @@ "step": "index_exercise" }, { - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "things = ['on', 'the', 'way', 'to', 'the', 'store']", "to_find = 'the'", @@ -2751,7 +2580,7 @@ "print(answer)" ], "response": { - "message": "

You're almost there! However, this prints the last index,\nnot the first one.

", + "message": "

\u4f60\u5feb\u5230\u4e86\uff01\u4f46\u662f\uff0c\u8fd9\u4f1a\u6253\u5370 \u6700\u540e \u4e00\u4e2a\u7d22\u5f15\uff0c\n\u800c\u4e0d\u662f\u7b2c\u4e00\u4e2a\u3002

", "passed": false, "result": [ { @@ -2769,7 +2598,7 @@ " print(i)", " break" ], - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "things = ['on', 'the', 'way', 'to', 'the', 'store']", "to_find = 'the'", @@ -2779,7 +2608,6 @@ " break" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2797,7 +2625,7 @@ " char2 = string2[i]", " print(char1 + ' ' + char2)" ], - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "string1 = 'Hello'", "string2 = 'World'", @@ -2807,7 +2635,6 @@ " print(char1 + ' ' + char2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2841,7 +2668,7 @@ "", " print(char1 + ' ' + char2)" ], - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "string1 = 'Goodbye'", "string2 = 'World'", @@ -2867,7 +2694,6 @@ " print(char1 + ' ' + char2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2879,13 +2705,13 @@ "step": "zip_longest_exercise" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "print(len)", "print(print)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2897,12 +2723,12 @@ "step": "print_functions" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "print(callable(len))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2914,14 +2740,14 @@ "step": "introducing_callable" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "f = 'a string'", "print(callable(f))", "f()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2940,11 +2766,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 3, "lines": [ { - "content": "f()", "is_current": true, "lineno": 3, + "text": "f()", "type": "line" } ], @@ -2958,13 +2786,13 @@ ] } ], - "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

The parenthesis () following f are interpreted\nby Python as a function call for f.\nHowever, f is not a function but an object of type str.

", + "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

Because of the surrounding parenthesis, ` \nis interpreted by Python as indicating a function call forf, which is an object of typestr`\nwhich cannot be called.

", "tail": "" } ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 3, in ", + " File \"/my_program.py\", line 3, in ", " 2 | print(callable(f))", "--> 3 | f()", " ^^^", @@ -2979,7 +2807,8 @@ "step": "not_callable" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "things = [1, 2, 3]", "length = len(things)", @@ -2987,7 +2816,6 @@ "print(printed)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2999,13 +2827,13 @@ "step": "print_returns_none" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "things = print([1, 2, 3])", "length = len(things)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3024,11 +2852,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 2, "lines": [ { - "content": "length = len(things)", "is_current": true, "lineno": 2, + "text": "length = len(things)", "type": "line" } ], @@ -3048,7 +2878,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 2, in ", + " File \"/my_program.py\", line 2, in ", " 1 | things = print([1, 2, 3])", "--> 2 | length = len(things)", " ^^^^^^^^^^^", @@ -3063,14 +2893,14 @@ "step": "len_of_none" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "word = 'Hello'", "print(word.upper)", "print(word.upper())" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3082,13 +2912,13 @@ "step": "methods_of_str" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "word = 'Hello'", "word.append('!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3101,11 +2931,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 2, "lines": [ { - "content": "word.append('!')", "is_current": true, "lineno": 2, + "text": "word.append('!')", "type": "line" } ], @@ -3125,7 +2957,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 2, in ", + " File \"/my_program.py\", line 2, in ", " 1 | word = 'Hello'", "--> 2 | word.append('!')", " ^^^^^^^^^^^", @@ -3140,7 +2972,8 @@ "step": "no_append_for_str" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "new_nums = nums + [4, 5]", @@ -3150,7 +2983,6 @@ "print(nums)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3162,14 +2994,14 @@ "step": "append_vs_concatenate" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "nums[1] = 9", "print(nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[1, 9, 3]", @@ -3180,7 +3012,7 @@ "[9, 2, 3]", "[1, 9, 3]", "[1, 2, 9]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3193,12 +3025,12 @@ "step": "subscript_assignment_predict" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "[7, 8, 9, 8].index(8)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -3209,7 +3041,7 @@ "1", "2", "3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3222,14 +3054,14 @@ "step": "index_predict_exercise" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "print(nums.pop(1))", "print(nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "2\n[1, 3]", @@ -3240,7 +3072,7 @@ "2\n[2, 3]", "1\n[2, 1, 3]", "2\n[2, 1, 3]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3253,14 +3085,14 @@ "step": "pop_predict_exercise" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "nums.remove(1)", "print(nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[2, 3]", @@ -3271,7 +3103,7 @@ "1", "2", "3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3284,19 +3116,14 @@ "step": "remove_predict_exercise" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "x.append(x.pop(0))", - "print(x)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = ['a', 'b', 'c']", "x.append(x.pop(0))", "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3308,19 +3135,14 @@ "step": "pop_remove_index_subscript_assignment" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "x[len(x) - 1] = x[0]", - "print(x)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = ['a', 'b', 'c']", "x[len(x) - 1] = x[0]", "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3332,19 +3154,14 @@ "step": "subscript_assignment_exercise" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "y = x + [x[0]]", - "print(y)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = ['a', 'b', 'c']", "y = x + [x[0]]", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3356,19 +3173,14 @@ "step": "negative_index_concatenation_exercise" }, { - "get_solution": [ - "x = [1, 2, 0, 3]", - "x.pop(x.index(0))", - "print(x)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [1, 2, 0, 3]", "x.pop(x.index(0))", "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3380,12 +3192,12 @@ "step": "remove_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "sorted([2, 9, 1, 8, 5, 6])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[1, 2, 5, 6, 8, 9]", @@ -3394,7 +3206,7 @@ "[1, 8, 6, 2, 5, 9]", "[1, 2, 5, 6, 8, 9]", "[2, 9, 1, 8, 5, 6]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3407,14 +3219,14 @@ "step": "sorted_predict_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [2, 9, 1, 8, 5, 64]", "print(7 in nums)", "print(2 in nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False\nTrue", @@ -3423,7 +3235,7 @@ "False\nTrue", "True\nTrue", "False\nFalse", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3436,12 +3248,12 @@ "step": "in_predict_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "sum([5, 3, 4])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "12", @@ -3449,7 +3261,7 @@ "10", "12", "7", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3462,12 +3274,12 @@ "step": "sum_predict_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "[1, 2, 3, 2, 7, 2, 5].count(2)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "3", @@ -3476,7 +3288,7 @@ "1", "2", "3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3489,19 +3301,14 @@ "step": "count_predict_exercise" }, { - "get_solution": [ - "x = [1, 2, 0, 3]", - "y = x.count(1) > 0", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [1, 2, 0, 3]", "y = x.count(1) > 0", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3513,19 +3320,14 @@ "step": "count_in_sorted_sum" }, { - "get_solution": [ - "x = [15, 12, -6, 3]", - "y = sum(x) / len(x)", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [15, 12, -6, 3]", "y = sum(x) / len(x)", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3537,19 +3339,14 @@ "step": "average_exercise" }, { - "get_solution": [ - "x = 100", - "y = sum(range(x + 1))", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = 100", "y = sum(range(x + 1))", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3561,19 +3358,14 @@ "step": "sum_range_exercise" }, { - "get_solution": [ - "x = [12, -6, 2, -1, 3]", - "y = sorted(x)[1]", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [12, -6, 2, -1, 3]", "y = sorted(x)[1]", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3585,12 +3377,12 @@ "step": "second_smallest_in_list_exercise" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "print('the' in 'feed the dog and the cat')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3602,14 +3394,14 @@ "step": "string_in_step" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "string = 'feed the dog and the cat'", "print(string.count('the'))", "print(string.index('the'))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3621,12 +3413,12 @@ "step": "string_count_index" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "'Python'.append(' is cool!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3639,11 +3431,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "'Python'.append(' is cool!')", "is_current": true, "lineno": 1, + "text": "'Python'.append(' is cool!')", "type": "line" } ], @@ -3658,7 +3452,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | 'Python'.append(' is cool!')", " ^^^^^^^^^^^^^^^", "", @@ -3671,7 +3465,8 @@ "step": "mutation_string_append" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "sentence = \"Python rocks!\"", "new_sentence = sentence.upper()", @@ -3679,7 +3474,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3691,15 +3485,12 @@ "step": "string_lower_upper" }, { - "get_solution": [ - "max([21, 55, 4, 91, 62, 49])" - ], - "page": "How to Find Information with Google, and more", + "get_solution": "program", + "page": "\u5982\u4f55\u4f7f\u7528\u8c37\u6b4c\u7b49\u67e5\u627e\u4fe1\u606f", "program": [ "max([21, 55, 4, 91, 62, 49])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3711,19 +3502,14 @@ "step": "sum_list" }, { - "get_solution": [ - "nums = [1, 2, 3, 4, 5]", - "nums.insert(2, 9)", - "print(nums)" - ], - "page": "How to Find Information with Google, and more", + "get_solution": "program", + "page": "\u5982\u4f55\u4f7f\u7528\u8c37\u6b4c\u7b49\u67e5\u627e\u4fe1\u606f", "program": [ "nums = [1, 2, 3, 4, 5]", "nums.insert(2, 9)", "print(nums)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3735,16 +3521,16 @@ "step": "list_insert" }, { - "page": "How to Find Information with Google, and more", + "get_solution": "program", + "page": "\u5982\u4f55\u4f7f\u7528\u8c37\u6b4c\u7b49\u67e5\u627e\u4fe1\u606f", "program": [ "dir([])" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']\n", + "text": "['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']\n", "type": "stdout" } ] @@ -3752,7 +3538,8 @@ "step": "dir_list" }, { - "page": "Understanding Programs With Python Tutor", + "get_solution": "program", + "page": "\u4f7f\u7528 Python Tutor \u7406\u89e3\u7a0b\u5e8f", "program": [ "all_numbers = [2, 4, 8, 1, 9, 7]", "", @@ -3769,7 +3556,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3781,7 +3567,8 @@ "step": "run_with_python_tutor" }, { - "page": "== vs is, and Having Multiple Names for One Value", + "get_solution": "program", + "page": "== \u4e0e is\uff0c\u4ee5\u53ca\u4e00\u4e2a\u503c\u7684\u591a\u4e2a\u540d\u79f0", "program": [ "list1 = [1, 2, 3]", "list2 = [1, 2, 3]", @@ -3798,7 +3585,6 @@ "print(list2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3810,7 +3596,8 @@ "step": "two_separate_lists" }, { - "page": "== vs is, and Having Multiple Names for One Value", + "get_solution": "program", + "page": "== \u4e0e is\uff0c\u4ee5\u53ca\u4e00\u4e2a\u503c\u7684\u591a\u4e2a\u540d\u79f0", "program": [ "list1 = [1, 2, 3]", "list2 = list1", @@ -3827,7 +3614,6 @@ "print(list2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3839,7 +3625,8 @@ "step": "same_list" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u8fed\u4ee3\u65f6\u7684\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "for i in range(len(numbers)):", @@ -3849,7 +3636,6 @@ "print(numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3862,11 +3648,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 3, "lines": [ { - "content": "number = numbers[i]", "is_current": true, "lineno": 3, + "text": "number = numbers[i]", "type": "line" } ], @@ -3906,7 +3694,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 3, in ", + " File \"/my_program.py\", line 3, in ", " 2 | for i in range(len(numbers)):", "--> 3 | number = numbers[i]", " ^^^^^^^^^^", @@ -3926,7 +3714,8 @@ "step": "run_broken_with_python_tutor" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u8fed\u4ee3\u65f6\u7684\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "for number in numbers:", @@ -3935,7 +3724,6 @@ "print(numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3947,7 +3735,8 @@ "step": "remove_instead_of_pop" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u8fed\u4ee3\u65f6\u7684\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "for number in numbers.copy():", @@ -3956,7 +3745,6 @@ "print(numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3968,7 +3756,8 @@ "step": "make_copy" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u8fed\u4ee3\u65f6\u7684\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "big_numbers = numbers.copy()", @@ -3979,7 +3768,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3991,7 +3779,8 @@ "step": "make_copy2" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u8fed\u4ee3\u65f6\u7684\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "big_numbers = []", @@ -4002,7 +3791,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4014,16 +3802,17 @@ "step": "make_new_list" }, { - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print('Alice's Diner')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print('Alice's Diner')\n ^\nSyntaxError: invalid syntax\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nI suspect that you were trying to use a quote character inside a string\nthat was enclosed in quotes of the same kind.\nPerhaps you should have escaped the inner quote character:\n\n print('Alice\\'s Diner')\n ^^\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You started writing a string with a single or double quote\nbut never ended the string with another quote on that line.

", + "text": " print('Alice's Diner')\n ^\nSyntaxError: unterminated string literal (detected at line 1)\n\u5728\u884c 1\n", "type": "syntax_error" } ] @@ -4031,12 +3820,12 @@ "step": "single_quotes_apostrophe" }, { - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print(\"Alice's Diner\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4048,19 +3837,19 @@ "step": "double_quotes" }, { - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "'Alice' == \"Alice\"" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4073,15 +3862,12 @@ "step": "single_double_quotes_equal" }, { - "get_solution": [ - "print(\"Special cases aren't special enough to break the rules.\")" - ], - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print(\"Special cases aren't special enough to break the rules.\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4093,15 +3879,12 @@ "step": "double_quote_exercise" }, { - "get_solution": [ - "print('\"Talk is cheap. Show me the code.\" - Linus Torvalds')" - ], - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print('\"Talk is cheap. Show me the code.\" - Linus Torvalds')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4113,6 +3896,7 @@ "step": "single_quote_exercise" }, { + "get_solution": "program", "page": "f-strings", "program": [ "name = \"Alice\"", @@ -4121,7 +3905,6 @@ "print(f\"{name} went to {meal} with {friend}.\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Alice went to lunch with Bob.", @@ -4135,7 +3918,7 @@ "'Alice' went to 'lunch' with 'Bob'.", "\"Alice went to lunch with Bob.\"", "Alice went to lunch with Bob.", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4148,6 +3931,7 @@ "step": "introduce_f_strings" }, { + "get_solution": "program", "page": "f-strings", "program": [ "name = \"Alice\"", @@ -4155,16 +3939,15 @@ "print(\"Hello \" + name + \". You are \" + age + \" years old.\")" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "\"Hello \" + name + \". You are \" + age + \" years old.\"", "Hello name. You are age years old.", "Hello Alice. You are 20 years old.", "Hello 'Alice'. You are 20 years old.", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4178,11 +3961,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 3, "lines": [ { - "content": "print("Hello " + name + ". You are " + age + " years old.")", "is_current": true, "lineno": 3, + "text": "print("Hello " + name + ". You are " + age + " years old.")", "type": "line" } ], @@ -4214,7 +3999,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 3, in ", + " File \"/my_program.py\", line 3, in ", " 2 | age = 20", "--> 3 | print(\"Hello \" + name + \". You are \" + age + \" years old.\")", " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", @@ -4232,11 +4017,7 @@ "step": "concatenate_string_number" }, { - "get_solution": [ - "name = \"Alice\"", - "age = 20", - "print(f'Hello {name}. You are {age} years old.')" - ], + "get_solution": "program", "page": "f-strings", "program": [ "name = \"Alice\"", @@ -4244,7 +4025,6 @@ "print(f'Hello {name}. You are {age} years old.')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4256,12 +4036,12 @@ "step": "basic_f_string_exercise" }, { + "get_solution": "program", "page": "f-strings", "program": [ "f\"2 * 3 + 4 is equal to {2 * 3 + 4}\"" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4278,15 +4058,14 @@ ], "page": "f-strings", "program": [ - "people = ['eODoUwNzS', 'ofHBEzZxs', 'zwTrQA', 'LDaOKmpHU', 'HCMLTt', 'NbRmEjaoyD']", + "people = ['Alice', 'Bob', 'Charlie']", "print(f\"There are {len(people)} people waiting, the first one's name is {people[0]}.\")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "There are 6 people waiting, the first one's name is eODoUwNzS.\n", + "text": "There are 3 people waiting, the first one's name is Alice.\n", "type": "stdout" } ] @@ -4294,7 +4073,8 @@ "step": "fix_broken_program" }, { - "page": "Introducing Nested Loops", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for letter in \"ABC\":", " print(letter)", @@ -4303,7 +4083,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "A\nA 0\nA 1\nA 2\nA 3\n---\nB\nB 0\nB 1\nB 2\nB 3\n---\nC\nC 0\nC 1\nC 2\nC 3\n---", @@ -4312,7 +4091,7 @@ "A\nA 0\nA 1\nA 2\nA 3\n---\nB\nB 0\nB 1\nB 2\nB 3\n---\nC\nC 0\nC 1\nC 2\nC 3\n---", "A 1\nA 2\nA 3\nA 4\n---\nB 1\nB 2\nB 3\nB 4\n---\nC 1\nC 2\nC 3\nC 4\n---", "A\nB\nC\n---\nA 0\nB 0\nC 0\n---\nA 1\nB 1\nC 1\n---\nA 2\nB 2\nC 2\n---\nA 3\nB 3\nC 3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4325,12 +4104,12 @@ "step": "first_nested_loop" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "print(1 + \"x\")" ], "response": { - "message": "

You can't add together strings and numbers. Use an f-string.

", + "message": "

\u4f60\u4e0d\u80fd\u5c06\u5b57\u7b26\u4e32\u548c\u6570\u5b57\u76f8\u52a0\u3002\u4f7f\u7528 f-string\u3002

", "passed": false, "result": [ { @@ -4343,11 +4122,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "print(1 + "x")", "is_current": true, "lineno": 1, + "text": "print(1 + "x")", "type": "line" } ], @@ -4362,7 +4143,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | print(1 + \"x\")", " ^^^^^^^", "", @@ -4375,25 +4156,25 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " for right in range(12):", " left += 1", " right += 1", " print(f'{left} x {right} = {left * right}')", - " print('----------')" + " print('---')" ], "response": { - "message": "

You added 1 to your outer loop variable at the wrong place!\nWhere should you do that instead to fix it?

", + "message": "

\u4f60\u5728\u9519\u8bef\u7684\u5730\u65b9\u7ed9\u5916\u90e8\u5faa\u73af\u53d8\u91cf\u52a0\u4e86 1\uff01\n\u4f60\u5e94\u8be5\u5728\u54ea\u91cc\u505a\u8fd9\u4e2a\u4ee5\u4fee\u590d\u5b83\uff1f

", "passed": false, "result": [ { - "text": "1 x 1 = 1\n2 x 2 = 4\n3 x 3 = 9\n4 x 4 = 16\n5 x 5 = 25\n6 x 6 = 36\n7 x 7 = 49\n8 x 8 = 64\n9 x 9 = 81\n10 x 10 = 100\n11 x 11 = 121\n12 x 12 = 144\n----------\n2 x 1 = 2\n3 x 2 = 6\n4 x 3 = 12\n5 x 4 = 20\n6 x 5 = 30\n7 x 6 = 42\n8 x 7 = 56\n9 x 8 = 72\n10 x 9 = 90\n11 x 10 = 110\n12 x 11 = 132\n13 x 12 = 156\n----------\n3 x 1 = 3\n4 x 2 = 8\n5 x 3 = 15\n6 x 4 = 24\n7 x 5 = 35\n8 x 6 = 48\n9 x 7 = 63\n10 x 8 = 80\n11 x 9 = 99\n12 x 10 = 120\n13 x 11 = 143\n14 x 12 = 168\n----------\n4 x 1 = 4\n5 x 2 = 10\n6 x 3 = 18\n7 x 4 = 28\n8 x 5 = 40\n9 x 6 = 54\n10 x 7 = 70\n11 x 8 = 88\n12 x 9 = 108\n13 x 10 = 130\n14 x 11 = 154\n15 x 12 = 180\n----------\n5 x 1 = 5\n6 x 2 = 12\n7 x 3 = 21\n8 x 4 = 32\n9 x 5 = 45\n10 x 6 = 60\n11 x 7 = 77\n12 x 8 = 96\n13 x 9 = 117\n14 x 10 = 140\n15 x 11 = 165\n16 x 12 = 192\n----------\n6 x 1 = 6\n7 x 2 = 14\n8 x 3 = 24\n9 x 4 = 36\n10 x 5 = 50\n11 x 6 = 66\n12 x 7 = 84\n13 x 8 = 104\n14 x 9 = 126\n15 x 10 = 150\n16 x 11 = 176\n17 x 12 = 204\n----------\n7 x 1 = 7\n8 x 2 = 16\n9 x 3 = 27\n10 x 4 = 40\n11 x 5 = 55\n12 x 6 = 72\n13 x 7 = 91", + "text": "1 x 1 = 1\n2 x 2 = 4\n3 x 3 = 9\n4 x 4 = 16\n5 x 5 = 25\n6 x 6 = 36\n7 x 7 = 49\n8 x 8 = 64\n9 x 9 = 81\n10 x 10 = 100\n11 x 11 = 121\n12 x 12 = 144\n---\n2 x 1 = 2\n3 x 2 = 6\n4 x 3 = 12\n5 x 4 = 20\n6 x 5 = 30\n7 x 6 = 42\n8 x 7 = 56\n9 x 8 = 72\n10 x 9 = 90\n11 x 10 = 110\n12 x 11 = 132\n13 x 12 = 156\n---\n3 x 1 = 3\n4 x 2 = 8\n5 x 3 = 15\n6 x 4 = 24\n7 x 5 = 35\n8 x 6 = 48\n9 x 7 = 63\n10 x 8 = 80\n11 x 9 = 99\n12 x 10 = 120\n13 x 11 = 143\n14 x 12 = 168\n---\n4 x 1 = 4\n5 x 2 = 10\n6 x 3 = 18\n7 x 4 = 28\n8 x 5 = 40\n9 x 6 = 54\n10 x 7 = 70\n11 x 8 = 88\n12 x 9 = 108\n13 x 10 = 130\n14 x 11 = 154\n15 x 12 = 180\n---\n5 x 1 = 5\n6 x 2 = 12\n7 x 3 = 21\n8 x 4 = 32\n9 x 5 = 45\n10 x 6 = 60\n11 x 7 = 77\n12 x 8 = 96\n13 x 9 = 117\n14 x 10 = 140\n15 x 11 = 165\n16 x 12 = 192\n---\n6 x 1 = 6\n7 x 2 = 14\n8 x 3 = 24\n9 x 4 = 36\n10 x 5 = 50\n11 x 6 = 66\n12 x 7 = 84\n13 x 8 = 104\n14 x 9 = 126\n15 x 10 = 150\n16 x 11 = 176\n17 x 12 = 204\n---\n7 x 1 = 7\n8 x 2 = 16\n9 x 3 = 27\n10 x 4 = 40\n11 x 5 = 55\n12 x 6 = 72\n13 x 7 = 91\n14 x 8 = 112\n15 x 9 = 135\n16 x 10 = 160\n17 x 11 = 187", "type": "stdout" }, { - "text": "\n14 x 8 = 112\n15 x 9 = 135\n16 x 10 = 160\n17 x 11 = 187\n18 x 12 = 216\n----------\n8 x 1 = 8\n9 x 2 = 18\n10 x 3 = 30\n11 x 4 = 44\n12 x 5 = 60\n13 x 6 = 78\n14 x 7 = 98\n15 x 8 = 120\n16 x 9 = 144\n17 x 10 = 170\n18 x 11 = 198\n19 x 12 = 228\n----------\n9 x 1 = 9\n10 x 2 = 20\n11 x 3 = 33\n12 x 4 = 48\n13 x 5 = 65\n14 x 6 = 84\n15 x 7 = 105\n16 x 8 = 128\n17 x 9 = 153\n18 x 10 = 180\n19 x 11 = 209\n20 x 12 = 240\n----------\n10 x 1 = 10\n11 x 2 = 22\n12 x 3 = 36\n13 x 4 = 52\n14 x 5 = 70\n15 x 6 = 90\n16 x 7 = 112\n17 x 8 = 136\n18 x 9 = 162\n19 x 10 = 190\n20 x 11 = 220\n21 x 12 = 252\n----------\n11 x 1 = 11\n12 x 2 = 24\n13 x 3 = 39\n14 x 4 = 56\n15 x 5 = 75\n16 x 6 = 96\n17 x 7 = 119\n18 x 8 = 144\n19 x 9 = 171\n20 x 10 = 200\n21 x 11 = 231\n22 x 12 = 264\n----------\n12 x 1 = 12\n13 x 2 = 26\n14 x 3 = 42\n15 x 4 = 60\n16 x 5 = 80\n17 x 6 = 102\n18 x 7 = 126\n19 x 8 = 152\n20 x 9 = 180\n21 x 10 = 210\n22 x 11 = 242\n23 x 12 = 276\n----------\n", + "text": "\n18 x 12 = 216\n---\n8 x 1 = 8\n9 x 2 = 18\n10 x 3 = 30\n11 x 4 = 44\n12 x 5 = 60\n13 x 6 = 78\n14 x 7 = 98\n15 x 8 = 120\n16 x 9 = 144\n17 x 10 = 170\n18 x 11 = 198\n19 x 12 = 228\n---\n9 x 1 = 9\n10 x 2 = 20\n11 x 3 = 33\n12 x 4 = 48\n13 x 5 = 65\n14 x 6 = 84\n15 x 7 = 105\n16 x 8 = 128\n17 x 9 = 153\n18 x 10 = 180\n19 x 11 = 209\n20 x 12 = 240\n---\n10 x 1 = 10\n11 x 2 = 22\n12 x 3 = 36\n13 x 4 = 52\n14 x 5 = 70\n15 x 6 = 90\n16 x 7 = 112\n17 x 8 = 136\n18 x 9 = 162\n19 x 10 = 190\n20 x 11 = 220\n21 x 12 = 252\n---\n11 x 1 = 11\n12 x 2 = 24\n13 x 3 = 39\n14 x 4 = 56\n15 x 5 = 75\n16 x 6 = 96\n17 x 7 = 119\n18 x 8 = 144\n19 x 9 = 171\n20 x 10 = 200\n21 x 11 = 231\n22 x 12 = 264\n---\n12 x 1 = 12\n13 x 2 = 26\n14 x 3 = 42\n15 x 4 = 60\n16 x 5 = 80\n17 x 6 = 102\n18 x 7 = 126\n19 x 8 = 152\n20 x 9 = 180\n21 x 10 = 210\n22 x 11 = 242\n23 x 12 = 276\n---\n", "type": "stdout" } ] @@ -4401,7 +4182,7 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " left += 1", @@ -4417,18 +4198,18 @@ " print(left, 'x 10 =', left * 10)", " print(left, 'x 11 =', left * 11)", " print(left, 'x 12 =', left * 12)", - " print('----------')" + " print('---')" ], "response": { - "message": "

Your solution is too long. You only need a few lines of code for this problem.\nUse a nested loop so that you don't need to repeat yourself.\nThe computer will do the repetition for you!

", + "message": "

\u4f60\u7684\u89e3\u51b3\u65b9\u6848\u592a\u957f\u4e86\u3002\u8fd9\u4e2a\u95ee\u9898\u53ea\u9700\u8981\u51e0\u884c\u4ee3\u7801\u3002\n\u4f7f\u7528\u5d4c\u5957\u5faa\u73af\uff0c\u8fd9\u6837\u4f60\u5c31\u4e0d\u9700\u8981\u91cd\u590d\u81ea\u5df1\u3002\n\u8ba1\u7b97\u673a\u4f1a\u4e3a\u4f60\u5b8c\u6210\u91cd\u590d\u7684\u5de5\u4f5c\uff01

", "passed": false, "result": [ { - "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n----------\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n----------\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n----------\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n----------\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n----------", + "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n---\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n---\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n---\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n---\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n---\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n---\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n---\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 =", "type": "stdout" }, { - "text": "\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 = 40\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n----------\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n----------\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n----------\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n", + "text": " 40\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n---\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n---\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n---\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n---\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n---\n", "type": "stdout" } ] @@ -4436,7 +4217,7 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " left += 1", @@ -4444,18 +4225,18 @@ " right += 1", " # for the sake of translation", " print(f'{left} x {right} = {left * right}'.replace('x', '*'))", - " print('----------')" + " print('---')" ], "response": { - "message": "

That's almost correct! Make sure to display the right character x in your table.\nFor example, your solution should display 3 x 4 = 12 and not 3 * 4 = 12.

", + "message": "

\u8fd9\u51e0\u4e4e\u662f\u6b63\u786e\u7684\uff01\u786e\u4fdd\u5728\u4f60\u7684\u8868\u4e2d\u663e\u793a\u6b63\u786e\u7684\u5b57\u7b26 x\u3002\n\u4f8b\u5982\uff0c\u4f60\u7684\u89e3\u51b3\u65b9\u6848\u5e94\u8be5\u663e\u793a 3 x 4 = 12 \u800c\u4e0d\u662f 3 * 4 = 12\u3002

", "passed": false, "result": [ { - "text": "1 * 1 = 1\n1 * 2 = 2\n1 * 3 = 3\n1 * 4 = 4\n1 * 5 = 5\n1 * 6 = 6\n1 * 7 = 7\n1 * 8 = 8\n1 * 9 = 9\n1 * 10 = 10\n1 * 11 = 11\n1 * 12 = 12\n----------\n2 * 1 = 2\n2 * 2 = 4\n2 * 3 = 6\n2 * 4 = 8\n2 * 5 = 10\n2 * 6 = 12\n2 * 7 = 14\n2 * 8 = 16\n2 * 9 = 18\n2 * 10 = 20\n2 * 11 = 22\n2 * 12 = 24\n----------\n3 * 1 = 3\n3 * 2 = 6\n3 * 3 = 9\n3 * 4 = 12\n3 * 5 = 15\n3 * 6 = 18\n3 * 7 = 21\n3 * 8 = 24\n3 * 9 = 27\n3 * 10 = 30\n3 * 11 = 33\n3 * 12 = 36\n----------\n4 * 1 = 4\n4 * 2 = 8\n4 * 3 = 12\n4 * 4 = 16\n4 * 5 = 20\n4 * 6 = 24\n4 * 7 = 28\n4 * 8 = 32\n4 * 9 = 36\n4 * 10 = 40\n4 * 11 = 44\n4 * 12 = 48\n----------\n5 * 1 = 5\n5 * 2 = 10\n5 * 3 = 15\n5 * 4 = 20\n5 * 5 = 25\n5 * 6 = 30\n5 * 7 = 35\n5 * 8 = 40\n5 * 9 = 45\n5 * 10 = 50\n5 * 11 = 55\n5 * 12 = 60\n----------\n6 * 1 = 6\n6 * 2 = 12\n6 * 3 = 18\n6 * 4 = 24\n6 * 5 = 30\n6 * 6 = 36\n6 * 7 = 42\n6 * 8 = 48\n6 * 9 = 54\n6 * 10 = 60\n6 * 11 = 66\n6 * 12 = 72\n----------\n7 * 1 = 7\n7 * 2 = 14\n7 * 3 = 21\n7 * 4 = 28\n7 * 5 = 35\n7 * 6 = 42\n7 * 7 = 49\n7 * 8 = 56\n7 * 9 = 63\n7 * 10 = 70\n7 * 11 = 77\n7 * 12 = 84\n----------", + "text": "1 * 1 = 1\n1 * 2 = 2\n1 * 3 = 3\n1 * 4 = 4\n1 * 5 = 5\n1 * 6 = 6\n1 * 7 = 7\n1 * 8 = 8\n1 * 9 = 9\n1 * 10 = 10\n1 * 11 = 11\n1 * 12 = 12\n---\n2 * 1 = 2\n2 * 2 = 4\n2 * 3 = 6\n2 * 4 = 8\n2 * 5 = 10\n2 * 6 = 12\n2 * 7 = 14\n2 * 8 = 16\n2 * 9 = 18\n2 * 10 = 20\n2 * 11 = 22\n2 * 12 = 24\n---\n3 * 1 = 3\n3 * 2 = 6\n3 * 3 = 9\n3 * 4 = 12\n3 * 5 = 15\n3 * 6 = 18\n3 * 7 = 21\n3 * 8 = 24\n3 * 9 = 27\n3 * 10 = 30\n3 * 11 = 33\n3 * 12 = 36\n---\n4 * 1 = 4\n4 * 2 = 8\n4 * 3 = 12\n4 * 4 = 16\n4 * 5 = 20\n4 * 6 = 24\n4 * 7 = 28\n4 * 8 = 32\n4 * 9 = 36\n4 * 10 = 40\n4 * 11 = 44\n4 * 12 = 48\n---\n5 * 1 = 5\n5 * 2 = 10\n5 * 3 = 15\n5 * 4 = 20\n5 * 5 = 25\n5 * 6 = 30\n5 * 7 = 35\n5 * 8 = 40\n5 * 9 = 45\n5 * 10 = 50\n5 * 11 = 55\n5 * 12 = 60\n---\n6 * 1 = 6\n6 * 2 = 12\n6 * 3 = 18\n6 * 4 = 24\n6 * 5 = 30\n6 * 6 = 36\n6 * 7 = 42\n6 * 8 = 48\n6 * 9 = 54\n6 * 10 = 60\n6 * 11 = 66\n6 * 12 = 72\n---\n7 * 1 = 7\n7 * 2 = 14\n7 * 3 = 21\n7 * 4 = 28\n7 * 5 = 35\n7 * 6 = 42\n7 * 7 = 49\n7 * 8 = 56\n7 * 9 = 63\n7 * 10 = 70\n7 * 11 = 77\n7 * 12 = 84\n---\n8 * 1 = 8\n8 * 2 = 16\n8 * 3 = 24\n8 * 4 = 32\n8 * 5 = 40", "type": "stdout" }, { - "text": "\n8 * 1 = 8\n8 * 2 = 16\n8 * 3 = 24\n8 * 4 = 32\n8 * 5 = 40\n8 * 6 = 48\n8 * 7 = 56\n8 * 8 = 64\n8 * 9 = 72\n8 * 10 = 80\n8 * 11 = 88\n8 * 12 = 96\n----------\n9 * 1 = 9\n9 * 2 = 18\n9 * 3 = 27\n9 * 4 = 36\n9 * 5 = 45\n9 * 6 = 54\n9 * 7 = 63\n9 * 8 = 72\n9 * 9 = 81\n9 * 10 = 90\n9 * 11 = 99\n9 * 12 = 108\n----------\n10 * 1 = 10\n10 * 2 = 20\n10 * 3 = 30\n10 * 4 = 40\n10 * 5 = 50\n10 * 6 = 60\n10 * 7 = 70\n10 * 8 = 80\n10 * 9 = 90\n10 * 10 = 100\n10 * 11 = 110\n10 * 12 = 120\n----------\n11 * 1 = 11\n11 * 2 = 22\n11 * 3 = 33\n11 * 4 = 44\n11 * 5 = 55\n11 * 6 = 66\n11 * 7 = 77\n11 * 8 = 88\n11 * 9 = 99\n11 * 10 = 110\n11 * 11 = 121\n11 * 12 = 132\n----------\n12 * 1 = 12\n12 * 2 = 24\n12 * 3 = 36\n12 * 4 = 48\n12 * 5 = 60\n12 * 6 = 72\n12 * 7 = 84\n12 * 8 = 96\n12 * 9 = 108\n12 * 10 = 120\n12 * 11 = 132\n12 * 12 = 144\n----------\n", + "text": "\n8 * 6 = 48\n8 * 7 = 56\n8 * 8 = 64\n8 * 9 = 72\n8 * 10 = 80\n8 * 11 = 88\n8 * 12 = 96\n---\n9 * 1 = 9\n9 * 2 = 18\n9 * 3 = 27\n9 * 4 = 36\n9 * 5 = 45\n9 * 6 = 54\n9 * 7 = 63\n9 * 8 = 72\n9 * 9 = 81\n9 * 10 = 90\n9 * 11 = 99\n9 * 12 = 108\n---\n10 * 1 = 10\n10 * 2 = 20\n10 * 3 = 30\n10 * 4 = 40\n10 * 5 = 50\n10 * 6 = 60\n10 * 7 = 70\n10 * 8 = 80\n10 * 9 = 90\n10 * 10 = 100\n10 * 11 = 110\n10 * 12 = 120\n---\n11 * 1 = 11\n11 * 2 = 22\n11 * 3 = 33\n11 * 4 = 44\n11 * 5 = 55\n11 * 6 = 66\n11 * 7 = 77\n11 * 8 = 88\n11 * 9 = 99\n11 * 10 = 110\n11 * 11 = 121\n11 * 12 = 132\n---\n12 * 1 = 12\n12 * 2 = 24\n12 * 3 = 36\n12 * 4 = 48\n12 * 5 = 60\n12 * 6 = 72\n12 * 7 = 84\n12 * 8 = 96\n12 * 9 = 108\n12 * 10 = 120\n12 * 11 = 132\n12 * 12 = 144\n---\n", "type": "stdout" } ] @@ -4463,17 +4244,18 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "pass", "3 x 4" ], "response": { - "message": "

To multiply numbers, use *

", + "message": "

\u8981\u4e58\u6570\u5b57\uff0c\u4f7f\u7528 *

", "passed": false, "result": [ { - "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\nat line 2\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nCurrently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.\n\nUnless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/aroberge/friendly/issues\n\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

Currently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.

\n

Unless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/friendly-traceback/friendly-traceback/issues

", + "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\n\u5728\u884c 2\n", "type": "syntax_error" } ] @@ -4481,33 +4263,25 @@ "step": "times_table_exercise" }, { - "get_solution": [ - "for left in range(12):", - " left += 1", - " for right in range(12):", - " right += 1", - " print(f'{left} x {right} = {left * right}')", - " print('----------')" - ], - "page": "Introducing Nested Loops", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " left += 1", " for right in range(12):", " right += 1", " print(f'{left} x {right} = {left * right}')", - " print('----------')" + " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n----------\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n----------\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n----------\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n----------\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n----------", + "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n---\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n---\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n---\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n---\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n---\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n---\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n---\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 = 40", "type": "stdout" }, { - "text": "\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 = 40\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n----------\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n----------\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n----------\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n", + "text": "\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n---\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n---\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n---\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n---\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n---\n", "type": "stdout" } ] @@ -4521,7 +4295,7 @@ " if player1 != player2:", " print(f'{player1} vs {player2}')" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "players = ['Alice', 'Bob', 'Charlie']", "for player1 in players:", @@ -4530,7 +4304,6 @@ " print(f'{player1} vs {player2}')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4549,7 +4322,7 @@ " for c4 in letters:", " print(c1 + c2 + c3 + c4)" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "letters = 'AB'", "for c1 in letters:", @@ -4559,7 +4332,6 @@ " print(c1 + c2 + c3 + c4)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4579,7 +4351,7 @@ " line += '+'", " print(line)" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "size = 3", "for i in range(size):", @@ -4590,7 +4362,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4608,7 +4379,7 @@ " if i < j:", " print(f'{players[i]} vs {players[j]}')" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "players = ['Alice', 'Bob', 'Charlie']", "for i in range(len(players)):", @@ -4617,7 +4388,6 @@ " print(f'{players[i]} vs {players[j]}')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4629,7 +4399,8 @@ "step": "player_vs_player_bonus" }, { - "page": "Understanding Programs with birdseye", + "get_solution": "program", + "page": "\u4f7f\u7528 birdseye \u7406\u89e3\u7a0b\u5e8f", "program": [ "a = 2", "b = 3", @@ -4638,7 +4409,6 @@ "print(a * b + c * d)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4650,7 +4420,8 @@ "step": "first_birdseye_example" }, { - "page": "Understanding Programs with birdseye", + "get_solution": "program", + "page": "\u4f7f\u7528 birdseye \u7406\u89e3\u7a0b\u5e8f", "program": [ "word = 'Amazing'", "vowels = []", @@ -4664,7 +4435,6 @@ "print(consonants)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4680,14 +4450,13 @@ "string = strings[1]", "print(string[0])" ], - "page": "Introducing Nested Lists", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abc', 'def', 'ghi']", "string = strings[1]", "print(string[0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4699,13 +4468,13 @@ "step": "string_list_exercise" }, { - "page": "Introducing Nested Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = [\"abc\", \"def\", \"ghi\"]", "print(strings[1][0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4720,13 +4489,12 @@ "get_solution": [ "print(strings[-2][-1])" ], - "page": "Introducing Nested Lists", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abc', 'de', 'fghi', 'jklmn', 'o']", "print(strings[-2][-1])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4738,13 +4506,13 @@ "step": "double_subscripting_exercise" }, { - "page": "Introducing Nested Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello', 'there'], ['how', 'are', 'you']]", "print(strings[1][0])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "how", @@ -4760,7 +4528,7 @@ "t", "e", "a", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4776,13 +4544,12 @@ "get_solution": [ "print(strings[1][2][0])" ], - "page": "Introducing Nested Lists", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello', 'there'], ['how', 'are', 'you']]", "print(strings[1][2][0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4794,7 +4561,8 @@ "step": "triple_subscripting" }, { - "page": "Looping Over Nested Lists", + "get_solution": "program", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "numbers = [[1, 2, 3], [4, 5], [6], []]", "for sublist in numbers:", @@ -4803,7 +4571,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1\n2\n3\n---\n4\n5\n---\n6\n---\n---", @@ -4813,7 +4580,7 @@ "1\n2\n3\n---\n4\n5\n---\n6\n---", "1 2 3\n---\n4 5\n---\n6\n---\n---", "1 2 3\n---\n4 5\n---\n6\n---", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4826,7 +4593,8 @@ "step": "nested_list_nested_loop_example" }, { - "page": "Looping Over Nested Lists", + "get_solution": "program", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "numbers = [[1, 2, 3], [4, 5], [6], []]", "for sublist in numbers:", @@ -4835,7 +4603,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4853,7 +4620,7 @@ " if word in string:", " print(string)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']]", "word = 'hello'", @@ -4863,7 +4630,6 @@ " print(string)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4883,7 +4649,7 @@ " present = True", " print(present)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']]", "word = 'goodbye'", @@ -4895,7 +4661,6 @@ " print(present)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4915,7 +4680,7 @@ " present = True", "print(present)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']]", "word = 'are'", @@ -4927,7 +4692,6 @@ "print(present)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4946,7 +4710,7 @@ " line += string[i]", " print(line)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abc', 'def', 'ghi']", "for i in range(len(strings[0])):", @@ -4956,7 +4720,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4983,7 +4746,7 @@ " line += string[i]", " print(line)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abcqwe', 'def', 'ghiq']", "lengths = []", @@ -5001,7 +4764,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5013,7 +4775,8 @@ "step": "zip_longest_strings_exercise" }, { - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def greet(name):", " print(f\"Hello {name}!\")", @@ -5022,7 +4785,6 @@ "greet(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5034,7 +4796,8 @@ "step": "define_greet" }, { - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def greet(name):", " print(f\"Hello {name}!\")", @@ -5044,7 +4807,6 @@ "greet(\"Bob\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello Alice!\nHow are you?\nHello Bob!\nHow are you?", @@ -5052,7 +4814,7 @@ "Hello Alice!\nHow are you?\nHello Bob!\nHow are you?", "Hello Alice!\nHello Bob!\nHow are you?", "Hello Alice!\nHow are you?\nHello Bob!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5065,15 +4827,8 @@ "step": "how_are_you" }, { - "get_solution": [ - "def say_hello(name):", - " print(f\"Hello {name}!\")", - " print(\"How are you?\")", - "", - "say_hello(\"Alice\")", - "say_hello(\"Bob\")" - ], - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def say_hello(name):", " print(f\"Hello {name}!\")", @@ -5083,7 +4838,6 @@ "say_hello(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5095,15 +4849,8 @@ "step": "change_function_name" }, { - "get_solution": [ - "def say_hello(person_name):", - " print(f\"Hello {person_name}!\")", - " print(\"How are you?\")", - "", - "say_hello(\"Alice\")", - "say_hello(\"Bob\")" - ], - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def say_hello(person_name):", " print(f\"Hello {person_name}!\")", @@ -5113,7 +4860,6 @@ "say_hello(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5125,26 +4871,22 @@ "step": "change_parameter_name" }, { - "get_solution": [ - "def print_twice(x):", - " print(x)", - " print(x)" - ], - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def print_twice(x):", " print(x)", " print(x)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "print_twice_exercise" }, { - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def print_many(thing, n):", " for _ in range(n):", @@ -5153,7 +4895,6 @@ "print_many(\"Hello\", 3)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello\nHello\nHello", @@ -5163,7 +4904,7 @@ "Hello\nHello\nHello", "Hello", "H\ne\nl\nl\no", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5176,15 +4917,9 @@ "step": "print_many" }, { - "get_solution": [ - "def print_many(n, thing):", - " for _ in range(n):", - " print(thing)", - "", - "print_many(3, \"Hello\")" - ], - "page": "Defining Functions", - "program": [ + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", + "program": [ "def print_many(n, thing):", " for _ in range(n):", " print(thing)", @@ -5192,7 +4927,6 @@ "print_many(3, \"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5204,7 +4938,8 @@ "step": "swap_parameters" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5216,7 +4951,6 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5228,7 +4962,8 @@ "step": "print_twice_call_print_many" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5240,83 +4975,55 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;245m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;245m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;245m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "text": "Hello", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"my_program.py\", line 5\u001b[0m\n\u001b[38;5;242m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n", + "text": "\n", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"my_program.py\", line 1\u001b[0m\n\u001b[38;5;242m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;242m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "Hello", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\n", "type": "stdout" }, { - "text": "Hello\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", - "type": "stdout" - }, - { - "text": "Hello\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", - "type": "stdout" - }, - { - "text": "", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "type": "snoop" } ] }, "step": "see_stack_in_snoop" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5328,7 +5035,6 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5340,7 +5046,8 @@ "step": "see_stack_in_pythontutor" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5352,7 +5059,6 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5364,7 +5070,8 @@ "step": "see_stack_in_birdseye" }, { - "page": "Returning Values From Functions", + "get_solution": "program", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def double(x):", " return x * 2", @@ -5375,7 +5082,6 @@ "print(twice)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "5\n10", @@ -5383,7 +5089,7 @@ "5\n5", "5\n10", "10\n10", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5396,7 +5102,8 @@ "step": "first_return" }, { - "page": "Returning Values From Functions", + "get_solution": "program", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def double(x):", " return x * 2", @@ -5406,14 +5113,13 @@ "print(number)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "5", "choices": [ "5", "10", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5426,13 +5132,13 @@ "step": "losing_return_value" }, { - "page": "Returning Values From Functions", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def quadruple(x):", " return x * 4" ], "response": { - "message": "

You cannot use *, +, or even any numbers inside quadruple.\nYou must call double to solve the problem.

", + "message": "

\u4f60\u4e0d\u80fd\u5728 quadruple \u5185\u90e8\u4f7f\u7528 *\u3001+\uff0c\u751a\u81f3\u4efb\u4f55\u6570\u5b57\u3002\n\u4f60\u5fc5\u987b\u8c03\u7528 double \u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u3002

", "passed": false, "result": [] }, @@ -5443,7 +5149,7 @@ "def quadruple(x):", " return double(double(x))" ], - "page": "Returning Values From Functions", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def double(x):", " return x * 2", @@ -5452,14 +5158,14 @@ " return double(double(x))" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "quadruple_exercise" }, { - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def double(x):", " return x * 2", @@ -5468,7 +5174,6 @@ "assert_equal(double(5), 10)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "OK\nOK", @@ -5478,7 +5183,7 @@ "Error! 2 != 4", "OK\nOK", "OK", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5491,7 +5196,8 @@ "step": "introducing_assert_equal" }, { - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def double(x):", " return x * 3", @@ -5500,7 +5206,6 @@ "assert_equal(double(5), 10)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Error! 6 != 4\nError! 15 != 10", @@ -5509,7 +5214,7 @@ "Error! 6 != 4\nError! 15 != 10", "Error! 4 != 6\nError! 10 != 15", "OK\nOK", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5522,7 +5227,8 @@ "step": "make_tests_fail" }, { - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def double(x):", " return x * 2", @@ -5534,7 +5240,6 @@ "assert_equal(quadruple(5), 20)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5546,24 +5251,20 @@ "step": "complete_quadruple_tests" }, { - "get_solution": [ - "def surround(string, sides):", - " return sides + string + sides" - ], - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def surround(string, sides):", " return sides + string + sides" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "surround_exercise" }, { - "page": "Testing Functions", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def surround(string, sides):", " return sides + string + sides", @@ -5575,21 +5276,21 @@ " return string" ], "response": { - "message": "

In the alert function, you placed your return statement at the wrong place!\nPay attention to your indentations in alert. You might be ending a loop too early with return.

", + "message": "

\u5728 alert \u51fd\u6570\u4e2d\uff0c\u4f60\u628a return \u8bed\u53e5\u653e\u9519\u4e86\u5730\u65b9\uff01\n\u6ce8\u610f\u4f60\u5728 alert \u4e2d\u7684\u7f29\u8fdb\u3002\u4f60\u53ef\u80fd\u8fc7\u65e9\u5730\u7528 return \u7ed3\u675f\u4e86\u4e00\u4e2a\u5faa\u73af\u3002

", "passed": false, "result": [] }, "step": "alert_exercise" }, { - "page": "Testing Functions", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def alert(string, level):", " marks = '!' * level", " return marks + ' ' + string + ' ' + marks" ], "response": { - "message": "

You cannot use string concatenation/formatting/interpolation/multiplication or f-strings in alert.\nYou must call surround to solve the problem.

", + "message": "

\u4f60\u4e0d\u80fd\u5728 alert \u4e2d\u4f7f\u7528\u5b57\u7b26\u4e32\u8fde\u63a5/\u683c\u5f0f\u5316/\u63d2\u503c/\u4e58\u6cd5\u6216 f-strings\u3002\n\u4f60\u5fc5\u987b\u8c03\u7528 surround \u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u3002

", "passed": false, "result": [] }, @@ -5603,7 +5304,7 @@ " string = surround(string, '!')", " return string" ], - "page": "Testing Functions", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def surround(string, sides):", " return sides + string + sides", @@ -5615,14 +5316,14 @@ " return string" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "alert_exercise" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return\u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def foo():", " return 1", @@ -5631,7 +5332,6 @@ "print(foo())" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -5641,7 +5341,7 @@ "[1, 2]", "1\n2", "1 2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5654,7 +5354,8 @@ "step": "double_return_in_one_function" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return\u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def double_numbers(numbers):", " for x in numbers:", @@ -5663,7 +5364,6 @@ "assert_equal(double_numbers([1, 2, 3]), [2, 4, 6])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5675,7 +5375,8 @@ "step": "cannot_return_multiple_values" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return\u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def foo():", " for letter in 'abc':", @@ -5687,7 +5388,6 @@ "foo()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "a 0\na 1\na 2\nb 0", @@ -5697,7 +5397,7 @@ "a 0\na 1\na 2\nb 0\nb 1\nb 2", "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", "a 0\na 1\na 2\nb 0\nb 1\nb 2\nc 0\nc 1\nc 2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5710,7 +5410,8 @@ "step": "return_ends_whole_function" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return\u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def foo():", " for letter in 'abc':", @@ -5722,7 +5423,6 @@ "foo()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", @@ -5732,7 +5432,7 @@ "a 0\na 1\na 2\nb 0\nb 1\nb 2", "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", "a 0\na 1\na 2\nb 0\nb 1\nb 2\nc 0\nc 1\nc 2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5745,7 +5445,8 @@ "step": "break_vs_return" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " if name == \"Alice\":", @@ -5760,7 +5461,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5772,19 +5472,19 @@ "step": "InputAliceBob" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "True or True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5797,19 +5497,19 @@ "step": "TrueOrTrue" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "True or False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5822,19 +5522,19 @@ "step": "TrueOrFalse" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "False or False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5847,7 +5547,8 @@ "step": "FalseOrFalse" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " if name == \"Alice\" or name == \"Bob\":", @@ -5860,7 +5561,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5872,7 +5572,8 @@ "step": "ImprovingWithOr" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " return name == \"Alice\" or name == \"Bob\"", @@ -5882,7 +5583,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5894,7 +5594,8 @@ "step": "FurtherImprovement" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " return name == \"Alice\" or \"Bob\"", @@ -5904,7 +5605,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5916,7 +5616,8 @@ "step": "ACommonMistake" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " return name == \"Alice\" or \"Bob\"", @@ -5926,7 +5627,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5938,14 +5638,8 @@ "step": "InspectWithBirdseye" }, { - "get_solution": [ - "def is_valid_percentage(x):", - " if x < 0 or x > 100:", - " return False", - " else:", - " return True" - ], - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_valid_percentage(x):", " if x < 0 or x > 100:", @@ -5954,26 +5648,25 @@ " return True" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AnExercise" }, { - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "True and True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5986,19 +5679,19 @@ "step": "TrueAndTrue" }, { - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "True and False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6011,19 +5704,19 @@ "step": "TrueAndFalse" }, { - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "False and False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6036,14 +5729,8 @@ "step": "FalseAndFalse" }, { - "get_solution": [ - "def is_valid_percentage(x):", - " if 0 <= x and x <= 100:", - " return True", - " else:", - " return False" - ], - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "def is_valid_percentage(x):", " if 0 <= x and x <= 100:", @@ -6052,41 +5739,37 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AndExercise" }, { - "get_solution": [ - "def all_equal(row):", - " return row[0] == row[1] and row[0] == row[2]" - ], - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "def all_equal(row):", " return row[0] == row[1] and row[0] == row[2]" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "TicTacToeWinningRow" }, { - "page": "Multi-line statements", + "get_solution": "program", + "page": "\u591a\u884c\u8bed\u53e5", "program": [ "is_friend = name == \"Alice\" or", " name == \"Bob\"" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " is_friend = name == \"Alice\" or\n ^\nSyntaxError: invalid syntax\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nThe Python keyword `or` can only be used for boolean expressions.\nPerhaps you meant to write\n\n`is_friend = name == \"Alice\" ,`\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

The Python keyword or can only be used for boolean expressions.\nPerhaps you meant to write

\n

is_friend = name == \"Alice\" ,

", + "text": " is_friend = name == \"Alice\" or\n ^\nSyntaxError: invalid syntax\n\u5728\u884c 1\n", "type": "syntax_error" } ] @@ -6094,7 +5777,8 @@ "step": "invalid_multiline" }, { - "page": "Multi-line statements", + "get_solution": "program", + "page": "\u591a\u884c\u8bed\u53e5", "program": [ "name = \"Bob\"", "", @@ -6114,7 +5798,6 @@ " name == \"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6126,12 +5809,12 @@ "step": "valid_multiline" }, { - "page": "Combining and and or", + "get_solution": "program", + "page": "\u7ec4\u5408 and \u548c or", "program": [ "True or False and False" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6143,15 +5826,8 @@ "step": "CombiningAndOr" }, { - "get_solution": [ - "def diagonal_winner(board):", - " middle = board[1][1]", - " return (", - " (middle == board[0][0] and middle == board[2][2]) or", - " (middle == board[0][2] and middle == board[2][0])", - " )" - ], - "page": "Combining and and or", + "get_solution": "program", + "page": "\u7ec4\u5408 and \u548c or", "program": [ "def diagonal_winner(board):", " middle = board[1][1]", @@ -6161,26 +5837,25 @@ " )" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AndHasHigherPriority" }, { - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "not True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6193,19 +5868,19 @@ "step": "IntroducingNot" }, { - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "not False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6218,13 +5893,13 @@ "step": "NotFalse" }, { - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "b = True", "print(not b or b)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6236,24 +5911,20 @@ "step": "NotTrueOrTrue" }, { - "get_solution": [ - "def invalid_image(filename):", - " return not (filename.endswith(\".png\") or filename.endswith(\".jpg\"))" - ], - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "def invalid_image(filename):", " return not (filename.endswith(\".png\") or filename.endswith(\".jpg\"))" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "NotPriority" }, { - "page": "Checking the board for winners", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def row_winner(board):", " for row in board:", @@ -6268,27 +5939,15 @@ " return False" ], "response": { - "message": "

Keep in mind that some entries might be ' '. An empty row is not a winning row.

", + "message": "

\u8bf7\u8bb0\u4f4f\uff0c\u6709\u4e9b\u6761\u76ee\u53ef\u80fd\u662f ' '\u3002\u7a7a\u884c\u4e0d\u662f\u83b7\u80dc\u884c\u3002

", "passed": false, "result": [] }, "step": "intro_row_winner" }, { - "get_solution": [ - "def row_winner(board):", - " for row in board:", - " all_equal = True", - " piece = row[0]", - " for entry in row:", - " if entry == ' ' or piece != entry:", - " all_equal = False", - " break", - " if all_equal:", - " return True", - " return False" - ], - "page": "Checking the board for winners", + "get_solution": "program", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def row_winner(board):", " for row in board:", @@ -6303,27 +5962,14 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "intro_row_winner" }, { - "get_solution": [ - "def column_winner(board):", - " for col in range(len(board[0])):", - " all_equal = True", - " piece = board[0][col]", - " for row in board:", - " if row[col] == ' ' or row[col] != piece:", - " all_equal = False", - " break", - " if all_equal:", - " return True", - " return False" - ], - "page": "Checking the board for winners", + "get_solution": "program", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def column_winner(board):", " for col in range(len(board[0])):", @@ -6338,27 +5984,14 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "column_winner" }, { - "get_solution": [ - "def diagonal_winner(board):", - " all_equal1 = True", - " all_equal2 = True", - " topleft = board[0][0]", - " topright = board[0][-1]", - " for i in range(len(board)):", - " if board[i][i] == ' ' or board[i][i] != topleft:", - " all_equal1 = False", - " if board[i][-i - 1] == ' ' or board[i][-i - 1] != topright:", - " all_equal2 = False", - " return all_equal1 or all_equal2" - ], - "page": "Checking the board for winners", + "get_solution": "program", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def diagonal_winner(board):", " all_equal1 = True", @@ -6373,7 +6006,6 @@ " return all_equal1 or all_equal2" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -6384,7 +6016,7 @@ "def winner(board):", " return row_winner(board) or column_winner(board) or diagonal_winner(board)" ], - "page": "Checking the board for winners", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def winning_line(strings):", " piece = strings[0]", @@ -6422,14 +6054,14 @@ " return row_winner(board) or column_winner(board) or diagonal_winner(board)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "winner" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "def print_board(board):", " for row in board:", @@ -6442,7 +6074,6 @@ "])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6454,7 +6085,8 @@ "step": "one_way_to_print_board" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "assert_equal(", " format_board([", @@ -6468,11 +6100,11 @@ ")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " \"XOX\n ^\nSyntaxError: EOL while scanning string literal\nat line 7\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nYou started writing a string with a single or double quote\nbut never ended the string with another quote on that line.\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You started writing a string with a single or double quote\nbut never ended the string with another quote on that line.

", + "text": " \"XOX\n ^\nSyntaxError: unterminated string literal (detected at line 7)\n\u5728\u884c 7\n", "type": "syntax_error" } ] @@ -6480,14 +6112,14 @@ "step": "invalid_multi_line_string" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "string = \"\"\"First line", "Second line\"\"\"", "print(string)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6499,24 +6131,24 @@ "step": "multi_line_strings_triple_quotes" }, { - "page": "The newline character, format_board", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "string = 'a'" ], "response": { - "message": "

Oops, string doesn't have the right value. Run the program from the previous step again.

", + "message": "

\u54ce\u5440\uff0cstring \u7684\u503c\u4e0d\u6b63\u786e\u3002\u8bf7\u518d\u6b21\u8fd0\u884c\u4e0a\u4e00\u6b65\u7684\u7a0b\u5e8f\u3002

", "passed": false, "result": [] }, "step": "discovering_newline" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "string" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6528,19 +6160,19 @@ "step": "discovering_newline" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "len('\\n')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", "choices": [ "1", "2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6553,17 +6185,8 @@ "step": "introducing_newline" }, { - "get_solution": [ - "def format_board(board):", - " result = ''", - " for i in range(len(board)):", - " for char in board[i]:", - " result += char", - " if i != len(board) - 1:", - " result += '\\n'", - " return result" - ], - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "def format_board(board):", " result = ''", @@ -6575,25 +6198,14 @@ " return result" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_simple" }, { - "get_solution": [ - "def format_board(board):", - " joined_rows = []", - " for row in board:", - " joined_rows.append(\"|\".join(row))", - " lines = []", - " for _ in board[0]:", - " lines.append(\"-\")", - " line = f'\\n{\"+\".join(lines)}\\n'", - " return line.join(joined_rows)" - ], - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "def format_board(board):", " joined_rows = []", @@ -6606,14 +6218,14 @@ " return line.join(joined_rows)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_bonus_challenge" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(type('Hello World'))", "print(type(23))", @@ -6622,7 +6234,6 @@ "print(type(4.56))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6634,12 +6245,12 @@ "step": "five_different_types" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "type(3) == int" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6651,14 +6262,14 @@ "step": "check_type_manually" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print('123')", "print(123)", "print(123 == '123')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6670,13 +6281,13 @@ "step": "different_types_look_same" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(123 + 456)", "print('123' + '456')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "579\n123456", @@ -6687,7 +6298,7 @@ "123456\n'123456'", "579\n123456", "579\n'123456'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6700,13 +6311,13 @@ "step": "plus_has_two_meanings" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(13 < 120)", "print('13' < '120')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True\nFalse", @@ -6715,7 +6326,7 @@ "True\nFalse", "False\nTrue", "False\nFalse", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6728,13 +6339,13 @@ "step": "less_than_has_two_meanings" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(sorted([120, 13, 0]))", "print(sorted(['120', '13', '0']))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[0, 13, 120]\n['0', '120', '13']", @@ -6745,7 +6356,7 @@ "[120, 13, 0]\n['0', '120', '13']", "[120, 13, 0]\n['13', '120', '0']", "[120, 13, 0]\n['120', '13', '0']", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6758,21 +6369,21 @@ "step": "less_than_sorting_strings" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "12 + '34'" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "46", "'46'", "1234", "'1234'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6786,11 +6397,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "12 + '34'", "is_current": true, "lineno": 1, + "text": "12 + '34'", "type": "line" } ], @@ -6805,7 +6418,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | 12 + '34'", " ^^^^^^^^^", "", @@ -6823,7 +6436,7 @@ " print('Starting... ' + str(i + 1))", "print('Go!')" ], - "page": "Types", + "page": "\u7c7b\u578b", "program": [ "number = '1'", "for i in range(int(number)):", @@ -6831,7 +6444,6 @@ "print('Go!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6843,18 +6455,8 @@ "step": "fixing_type_errors_with_conversion" }, { - "get_solution": [ - "def format_board(board):", - " first_row = ' '", - " for i in range(len(board)):", - " first_row += str(i + 1)", - " joined_rows = [first_row]", - " for i in range(len(board)):", - " joined_row = str(i + 1) + ''.join(board[i])", - " joined_rows.append(joined_row)", - " return \"\\n\".join(joined_rows)" - ], - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "def format_board(board):", " first_row = ' '", @@ -6867,21 +6469,20 @@ " return \"\\n\".join(joined_rows)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_with_numbers" }, { - "page": "Interactive Programs with input()", + "get_solution": "program", + "page": "\u4f7f\u7528 input() \u7684\u4ea4\u4e92\u5f0f\u7a0b\u5e8f", "program": [ "print('Type your name, then press Enter:')", "name = input()", "print(f'Hello {name}!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6906,7 +6507,6 @@ }, { "get_solution": [ - "super_secret_number = 7", "print(\"What number am I thinking of?\")", "guess = input()", "if int(guess) == super_secret_number:", @@ -6914,7 +6514,7 @@ "else:", " print(\"Nope!\")" ], - "page": "Interactive Programs with input()", + "page": "\u4f7f\u7528 input() \u7684\u4ea4\u4e92\u5f0f\u7a0b\u5e8f", "program": [ "super_secret_number = 7", "print(\"What number am I thinking of?\")", @@ -6925,7 +6525,6 @@ " print(\"Nope!\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6949,7 +6548,8 @@ "step": "convert_input_to_int" }, { - "page": "Nested List Assignment: Playing Moves on the Board", + "get_solution": "program", + "page": "\u5d4c\u5957\u5217\u8868\u4f5c\u4e1a\uff1a\u5728\u68cb\u76d8\u4e0a\u8fdb\u884c\u79fb\u52a8", "program": [ "def play_move(board, player):", " board[1] = player", @@ -6962,7 +6562,6 @@ "play_game()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[' ', 'X', ' ']", @@ -6976,7 +6575,7 @@ "['X', ' ', ' ']", "[' ', 'X', ' ']", "[' ', ' ', 'X']", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6989,7 +6588,8 @@ "step": "modify_list_in_function" }, { - "page": "Nested List Assignment: Playing Moves on the Board", + "get_solution": "program", + "page": "\u5d4c\u5957\u5217\u8868\u4f5c\u4e1a\uff1a\u5728\u68cb\u76d8\u4e0a\u8fdb\u884c\u79fb\u52a8", "program": [ "def play_move(board, player):", " row = board[1]", @@ -7007,7 +6607,6 @@ "play_game()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7019,13 +6618,8 @@ "step": "nested_assignment_two_lines" }, { - "get_solution": [ - "def play_move(board, player):", - " row = int(input()) - 1", - " col = int(input()) - 1", - " board[row][col] = player" - ], - "page": "Nested List Assignment: Playing Moves on the Board", + "get_solution": "program", + "page": "\u5d4c\u5957\u5217\u8868\u4f5c\u4e1a\uff1a\u5728\u68cb\u76d8\u4e0a\u8fdb\u884c\u79fb\u52a8", "program": [ "def play_move(board, player):", " row = int(input()) - 1", @@ -7033,14 +6627,14 @@ " board[row][col] = player" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "nested_assignment_input" }, { - "page": "Making the Board", + "get_solution": "program", + "page": "\u5236\u4f5c\u68cb\u76d8", "program": [ "def make_board(size):", " row = []", @@ -7068,7 +6662,6 @@ "test()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7080,30 +6673,21 @@ "step": "naive_make_board" }, { - "page": "Making the Board", + "page": "\u5236\u4f5c\u68cb\u76d8", "program": [ "pass", "def make_board(size): return [[' '] * size] * size" ], "response": { - "message": "

The sublists in the result are not all separate objects.

", + "message": "

\u7ed9\u5b9a\u8fd9\u4e9b\u503c\uff1a

\n
size = 2\n
\n

\u4f60\u7684\u4ee3\u7801\u8f93\u51fa\uff1a

\n
[[' ', ' '], [' ', ' ']]\n
\n

\u54ea\u4e00\u4e2a\u662f\u6b63\u786e\u7684\uff01

\n

\u7136\u800c\uff0c\u7ed3\u679c\u4e2d\u7684\u5b50\u5217\u8868\u5e76\u4e0d\u662f\u6240\u6709\u72ec\u7acb\u7684\u5bf9\u8c61\u3002

", "passed": false, "result": [] }, "step": "fix_make_board" }, { - "get_solution": [ - "def make_board(size):", - " board = []", - " for _ in range(size):", - " row = []", - " for _ in range(size):", - " row.append(' ')", - " board.append(row)", - " return board" - ], - "page": "Making the Board", + "get_solution": "program", + "page": "\u5236\u4f5c\u68cb\u76d8", "program": [ "def make_board(size):", " board = []", @@ -7115,7 +6699,6 @@ " return board" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -7142,7 +6725,7 @@ "", " print_draw()" ], - "page": "The Full Tic-Tac-Toe Game", + "page": "\u5b8c\u6574\u7684\u4e95\u5b57\u68cb\u6e38\u620f", "program": [ "def winning_line(strings):", " strings = set(strings)", @@ -7205,10 +6788,445 @@ " print_draw()" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "the_full_game" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {'apple': 'pomme', 'box': 'boite'}" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "first_dict" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french[0]" + ], + "response": { + "passed": true, + "result": [ + { + "data": [ + { + "didyoumean": [], + "exception": { + "message": "0", + "type": "KeyError" + }, + "frames": [ + { + "filename": "/my_program.py", + "lineno": 1, + "lines": [ + { + "is_current": true, + "lineno": 1, + "text": "french[0]", + "type": "line" + } + ], + "name": "", + "type": "frame", + "variables": [ + { + "name": "french\n", + "value": "{'apple': 'pomme', 'box': 'boite'}\n" + } + ] + } + ], + "friendly": "

A KeyError is raised when a value is not found as a\nkey in a Python dict or in a similar object.

\n

The key 0 cannot be found in the dict french.

", + "tail": "" + } + ], + "text": [ + "Traceback (most recent call last):", + " File \"/my_program.py\", line 1, in ", + "--> 1 | french[0]", + " ^^^^^^^^^", + "french = {'apple': 'pomme', 'box': 'boite'}", + "", + "KeyError: 0" + ], + "type": "traceback" + } + ] + }, + "step": "dict_access" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access2" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french['apple']" + ], + "response": { + "passed": true, + "result": [ + { + "text": "'pomme'\n", + "type": "stdout" + } + ] + }, + "step": "dict_access2" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access3" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french['box']" + ], + "response": { + "passed": true, + "result": [ + { + "text": "'boite'\n", + "type": "stdout" + } + ] + }, + "step": "dict_access3" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access4" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french['pomme']" + ], + "response": { + "passed": true, + "result": [ + { + "data": [ + { + "didyoumean": [], + "exception": { + "message": "'pomme'", + "type": "KeyError" + }, + "frames": [ + { + "filename": "/my_program.py", + "lineno": 1, + "lines": [ + { + "is_current": true, + "lineno": 1, + "text": "french['pomme']", + "type": "line" + } + ], + "name": "", + "type": "frame", + "variables": [ + { + "name": "french\n", + "value": "{'apple': 'pomme', 'box': 'boite'}\n" + } + ] + } + ], + "friendly": "

A KeyError is raised when a value is not found as a\nkey in a Python dict or in a similar object.

\n

The key 'pomme' cannot be found in the dict french.

", + "tail": "" + } + ], + "text": [ + "Traceback (most recent call last):", + " File \"/my_program.py\", line 1, in ", + "--> 1 | french['pomme']", + " ^^^^^^^^^^^^^^^", + "french = {'apple': 'pomme', 'box': 'boite'}", + "", + "KeyError: 'pomme'" + ], + "type": "traceback" + } + ] + }, + "step": "dict_access4" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def total_cost(cart, prices):", + " result = 0", + " for item in cart:", + " price = prices[item]", + " result += price", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "shopping_cart1" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def total_cost(cart, quantities, prices):", + " result = 0", + " for item in cart:", + " price = prices[item]", + " quantity = quantities[item]", + " result += price * quantity", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "shopping_cart4" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def substitute(string):", + " result = ''", + " for char in string:", + " if char == 'A':", + " char = 'T'", + " elif char == 'T':", + " char = 'A'", + " elif char == 'G':", + " char = 'C'", + " elif char == 'C':", + " char = 'G'", + " result += char", + " return result", + "", + "original = 'AGTAGCGTCCTTAGTTACAGGATGGCTTAT'", + "expected = 'TCATCGCAGGAATCAATGTCCTACCGAATA'", + "assert_equal(substitute(original), expected)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "OK\n", + "type": "stdout" + } + ] + }, + "step": "dna_part1" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def substitute(string, d):", + " result = \"\"", + " for letter in string:", + " result += d[letter]", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "dna_part2" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "quantities = {'apple': 1, 'cat': 10}", + "print(quantities.keys())" + ], + "response": { + "passed": true, + "result": [ + { + "text": "dict_keys(['apple', 'cat'])\n", + "type": "stdout" + } + ] + }, + "step": "introducing_keys" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "quantities = {'apple': 1, 'cat': 10}", + "for key in quantities.keys():", + " print(key)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "apple\ncat\n", + "type": "stdout" + } + ] + }, + "step": "keys_are_iterable" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "quantities = {'apple': 1, 'cat': 10}", + "for key in quantities:", + " print(key)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "apple\ncat\n", + "type": "stdout" + } + ] + }, + "step": "keys_are_iterable2" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def total_cost(quantities, prices):", + " result = 0", + " for item in quantities:", + " price = prices[item]", + " quantity = quantities[item]", + " result += price * quantity", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "cleanup_shopping_cart" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def print_words(french):", + " for word in french:", + " print(\"English: \" + word)", + " print(\"French: \" + french[word])", + " print(\"---\")" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "english_to_french" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def print_words(french, german):", + " for word in french:", + " print(\"English: \" + word)", + " print(\"French: \" + french[word])", + " print(\"German: \" + german[word])", + " print(\"---\")" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "english_to_german" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def print_words(words):", + " for word in words:", + " translations = words[word]", + "", + " print(f\"English: {word}\")", + " for language in translations:", + " print(f\"{language}: {translations[language]}\")", + " print(f\"---\")", + "", + "print_words({", + " 'apple': {", + " 'French': 'pomme',", + " 'German': 'apfel',", + " },", + " 'box': {", + " 'French': 'boite',", + " 'German': 'kasten',", + " },", + "})" + ], + "response": { + "passed": true, + "result": [ + { + "text": "English: apple\nFrench: pomme\nGerman: apfel\n---\nEnglish: box\nFrench: boite\nGerman: kasten\n---\n", + "type": "stdout" + } + ] + }, + "step": "nested_dictionaries" } ] \ No newline at end of file diff --git a/translations/locales/zh/LC_MESSAGES/futurecoder.mo b/translations/locales/zh/LC_MESSAGES/futurecoder.mo index e79c1c4806dd8520f7dd873878398fca2e79e183..658f0ce5ceb2c7de163da161d4015e5c9bc4c7af 100644 GIT binary patch literal 299032 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%0DL_vBx=hu@>1{a100YH(D{0#eo4k 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 S7W;tA;-Y+Ia-G*R@_zt&m|&Oy literal 103009 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 TranslationRules: + """Get translation rules for a language code.""" + try: + return cls[language_code.upper()].value + except KeyError: + raise ValueError(f"Unsupported language code: {language_code}") + + @classmethod + def add_language(cls, language_code: str, language_name: str, plural_forms: str) -> None: + """Add a new language to the supported languages. + + Args: + language_code: Two-letter language code (e.g., 'es' for Spanish) + language_name: Full name of the language + plural_forms: Plural forms expression for the language + """ + # Create new TranslationRules instance + rules = TranslationRules( + language_name=language_name, + language_code=language_code, + plural_forms=plural_forms, + context=BASE_TEACHING_CONTEXT.format(language_name=language_name) + ) + + # Add to enum + cls._member_map_[language_code.upper()] = rules + cls._member_names_.append(language_code.upper()) + cls._value2member_map_[rules] = rules + +class POFileSplitter: + def __init__(self, input_file: str, base_output_dir: str, chunk_size: int): + """Initialize the PO file splitter. + + Args: + input_file: Path to the input PO file + base_output_dir: Base directory for chunks (will create chunks/en/ subdirectory) + chunk_size: Maximum number of entries per chunk (for large chapters) + """ + self.input_file = input_file + self.base_output_dir = Path(base_output_dir) + self.en_chunks_dir = self.base_output_dir / "chunks" / "en" + self.chunk_size = chunk_size + self.logger = logging.getLogger(__name__) + self.logger.info(f"Initializing POFileSplitter with input: {input_file}, output: {self.en_chunks_dir}, max chunk size: {chunk_size}") + + def extract_chapter_name(self, msgid: str) -> str: + """Extract chapter name from msgid.""" + # Handle different msgid patterns + if msgid.startswith('pages.'): + # Extract chapter from patterns like: pages.IntroducingNestedLoops.steps.crack_password_exercise.hints.0.text + parts = msgid.split('.') + if len(parts) >= 2: + return parts[1] # IntroducingNestedLoops + elif msgid.startswith('frontend.'): + # Frontend UI elements + return 'frontend_ui' + elif 'hint' in msgid.lower(): + # Hint-related entries + return 'hints' + elif 'code_bits.' in msgid: + # Code bits + return 'code_bits' + elif any(marker in msgid for marker in ['__program__', '__code', '__copyable__']): + # Special markers + return 'special_markers' + else: + # General/uncategorized entries + return 'general' + + def split_entries(self) -> None: + """Split the PO file into chunks organized by chapters and save to chunks/en/.""" + try: + # Load the PO file + self.logger.info(f"Loading PO file: {self.input_file}") + po_file = polib.pofile(self.input_file) + total_entries = len(po_file) + self.logger.info(f"Found {total_entries} entries to split") + + # Group entries by chapter + chapters = defaultdict(list) + for entry in po_file: + chapter_name = self.extract_chapter_name(entry.msgid) + chapters[chapter_name].append(entry) + + self.logger.info(f"Organized entries into {len(chapters)} chapters:") + for chapter, entries in chapters.items(): + self.logger.info(f" - {chapter}: {len(entries)} entries") + + # Create English chunks directory + self.en_chunks_dir.mkdir(parents=True, exist_ok=True) + self.logger.info(f"Created English chunks directory: {self.en_chunks_dir}") + + # Save each chapter as one or more chunks to en/ directory + chunk_count = 0 + for chapter_name, entries in chapters.items(): + # If chapter has too many entries, split into multiple chunks + if len(entries) <= self.chunk_size: + # Single chunk for this chapter + chunk_count += 1 + chunk_file = self.en_chunks_dir / f"{chapter_name}.po" + self.save_chunk(entries, chunk_file, po_file.metadata) + self.logger.info(f"Saved chapter '{chapter_name}' to {chunk_file}") + else: + # Split large chapter into multiple chunks + num_chunks = (len(entries) + self.chunk_size - 1) // self.chunk_size + for i in range(num_chunks): + start_idx = i * self.chunk_size + end_idx = min((i + 1) * self.chunk_size, len(entries)) + chunk_entries = entries[start_idx:end_idx] + + chunk_count += 1 + chunk_file = self.en_chunks_dir / f"{chapter_name}_part{i+1:02d}.po" + self.save_chunk(chunk_entries, chunk_file, po_file.metadata) + self.logger.info(f"Saved chapter '{chapter_name}' part {i+1}/{num_chunks} to {chunk_file}") + + self.logger.info(f"Successfully split PO file into {chunk_count} chapter-based chunks in {self.en_chunks_dir}") + + except Exception as e: + self.logger.error(f"Error splitting PO file: {str(e)}") + raise + + def save_chunk(self, entries: List[polib.POEntry], chunk_file: Path, metadata: dict): + """Save a chunk of entries to a PO file.""" + chunk_po = polib.POFile() + chunk_po.metadata = metadata.copy() + chunk_po.extend(entries) + chunk_po.save(str(chunk_file)) + +class Translator: + def __init__(self, config: TranslationConfig, language_code: str): + """Initialize the translator. + + Args: + config: Translation configuration + language_code: Language code to translate to + """ + self.config = config + self.language_code = language_code + self.rules = Language.get_rules(language_code) + self.logger = logging.getLogger(__name__) + self.logger.info(f"Initialized translator for {self.rules.language_name}") + + # Initialize HTTP session + self.session = requests.Session() + self.session.headers.update({ + "Authorization": f"Bearer {config.api_key}", + "Content-Type": "application/json" + }) + + def is_chunk_translated(self, chunk_file: str) -> bool: + """Check if a chunk file is already translated.""" + try: + chunk = polib.pofile(chunk_file) + total_entries = len(chunk) + translated_entries = 0 + + for entry in chunk: + if entry.msgstr and entry.msgstr.strip(): + translated_entries += 1 + elif entry.msgstr_plural: + # Check if any plural form is translated + if any(msgstr.strip() for msgstr in entry.msgstr_plural.values()): + translated_entries += 1 + + # Consider chunk translated if at least 80% of entries are translated + translation_percentage = (translated_entries / total_entries) * 100 if total_entries > 0 else 0 + is_translated = translation_percentage >= 80 + + self.logger.debug(f"Chunk {os.path.basename(chunk_file)}: {translated_entries}/{total_entries} entries translated ({translation_percentage:.1f}%)") + + return is_translated + + except Exception as e: + self.logger.error(f"Error checking translation status of {chunk_file}: {str(e)}") + return False + + def prepare_translation_request(self, chunk: polib.POFile) -> Dict: + """Prepare the translation request payload.""" + # Convert PO entries to text format + entries_text = [] + for entry in chunk: + # Add special markers to help preserve special strings and formatting + entry_text = f"msgid: {entry.msgid}\n" + if entry.msgstr: + # Mark special strings with a unique marker + msgstr = entry.msgstr + + # Special handling for misc terms + if entry.msgid.startswith("misc_terms."): + # For misc terms, preserve all newlines and formatting exactly + msgstr = msgstr.replace('\n', '') + # Also preserve markdown formatting + msgstr = msgstr.replace('*', '') + msgstr = msgstr.replace('**', '') + msgstr = msgstr.replace('`', '') + msgstr = msgstr.replace('[', '') + msgstr = msgstr.replace(']', '') + msgstr = msgstr.replace('(', '') + msgstr = msgstr.replace(')', '') + else: + # For regular entries, just preserve newlines + msgstr = msgstr.replace('\n', '') + + # Mark special strings + msgstr = re.sub(r'(__\w+__)', r'\1', msgstr) + entry_text += f"msgstr: {msgstr}\n" + if entry.msgid_plural: + entry_text += f"msgid_plural: {entry.msgid_plural}\n" + for i, msgstr in enumerate(entry.msgstr_plural.values()): + # Mark newlines and special strings in plural forms too + msgstr = msgstr.replace('\n', '') + msgstr = re.sub(r'(__\w+__)', r'\1', msgstr) + entry_text += f"msgstr[{i}]: {msgstr}\n" + entries_text.append(entry_text) + + # Combine all entries + text_to_translate = "\n\n".join(entries_text) + self.logger.debug(f"Prepared text to translate (first 100 chars): {text_to_translate[:100]}") + + # Prepare the system message with rules + system_message = f"""You are a professional translator. Your task is to translate the following PO file entries from English to {self.rules.language_name}. + +{self.rules.context} + +The input will be in PO file format with msgid (English) and msgstr (translation) pairs. +Only translate the text in the msgstr fields, keeping all other formatting, markers, and structure exactly as is. + +Special formatting rules: +1. Special strings marked with tags must be preserved exactly as they are +2. Newlines marked with must be preserved exactly as they are, including their position and count +3. For misc_terms entries (starting with "misc_terms."): + - Preserve all newlines exactly as they appear in the original + - Preserve all markdown formatting: + * for italics (*) + * for bold (**) + * for code blocks (`) + * and for links ([ and ]) + * and for URLs (( and )) + - Keep all URLs and links unchanged + - Maintain the exact same number of newlines as the original + +Return the translated text in the same PO file format.""" + + return { + "model": self.config.model, + "messages": [ + {"role": "system", "content": system_message}, + {"role": "user", "content": text_to_translate} + ], + "temperature": 0.3 + } + + def translate_chunk(self, en_chunk_file: str, target_chunk_file: str) -> Optional[polib.POFile]: + """Translate a chunk from English to target language.""" + try: + # Check if target chunk already exists and is translated + if os.path.exists(target_chunk_file) and self.is_chunk_translated(target_chunk_file): + self.logger.info(f"Skipping already translated chunk: {os.path.basename(target_chunk_file)}") + return polib.pofile(target_chunk_file) + + self.logger.info(f"Translating {os.path.basename(en_chunk_file)} → {os.path.basename(target_chunk_file)}") + + # Load the English chunk + self.logger.debug(f"Loading English chunk: {en_chunk_file}") + chunk = polib.pofile(en_chunk_file) + self.logger.debug(f"Loaded chunk with {len(chunk)} entries") + + # Prepare translation request + payload = self.prepare_translation_request(chunk) + self.logger.debug("Prepared translation request") + + # Make API call + self.logger.debug(f"Making API call to {self.config.base_url}") + response = self.session.post(self.config.base_url, json=payload) + + if response.status_code == 200: + result = response.json() + translated_text = result['choices'][0]['message']['content'] + self.logger.debug(f"Received translation (first 100 chars): {translated_text[:100]}") + + # Parse the translated text and update the chunk + updated_chunk = self.parse_translated_text(translated_text, chunk) + + if updated_chunk: + # Ensure target directory exists + os.makedirs(os.path.dirname(target_chunk_file), exist_ok=True) + # Save to target language directory + updated_chunk.save(target_chunk_file) + self.logger.info(f"Successfully translated and saved: {os.path.basename(target_chunk_file)}") + return updated_chunk + else: + self.logger.error(f"Failed to parse translated text for {en_chunk_file}") + return None + else: + self.logger.error(f"API error {response.status_code}: {response.text}") + return None + + except Exception as e: + self.logger.error(f"Error translating chunk {en_chunk_file}: {str(e)}") + return None + + def parse_translated_text(self, translated_text: str, original_chunk: polib.POFile) -> Optional[polib.POFile]: + """Parse the translated text and update the original chunk with translations.""" + try: + self.logger.debug("Parsing translated text") + translated_lines = translated_text.split('\n') + current_entry = None + current_key = None + + for line in translated_lines: + line = line.strip() + if not line: + continue + + if line.startswith('msgid: '): + current_key = 'msgid' + msgid = line[7:].strip() + # Find the entry in the original chunk + current_entry = original_chunk.find(msgid) + if current_entry: + self.logger.debug(f"Found entry for msgid: {msgid[:50]}...") + else: + self.logger.warning(f"Could not find entry for msgid: {msgid[:50]}...") + + elif line.startswith('msgid_plural: '): + current_key = 'msgid_plural' + msgid_plural = line[14:].strip() + if current_entry and current_entry.msgid_plural == msgid_plural: + self.logger.debug(f"Found entry for msgid_plural: {msgid_plural[:50]}...") + + elif line.startswith('msgstr: '): + if current_entry and current_key == 'msgid': + translation = line[8:].strip() + + # Special handling for misc terms + if current_entry.msgid.startswith("misc_terms."): + # Restore markdown formatting + translation = translation.replace('', '*') + translation = translation.replace('', '**') + translation = translation.replace('', '`') + translation = translation.replace('', '[') + translation = translation.replace('', ']') + translation = translation.replace('', '(') + translation = translation.replace('', ')') + + # Restore newlines and special strings + translation = translation.replace('', '\n') + translation = re.sub(r'(__\w+__)', r'\1', translation) + + if translation and translation != current_entry.msgid: # Only update if actually translated + current_entry.msgstr = translation + self.logger.debug(f"Updated msgstr for entry: {current_entry.msgid[:50]}...") + + elif line.startswith('msgstr[0]: '): + if current_entry and current_key == 'msgid_plural': + translation = line[11:].strip() + # Restore newlines and special strings + translation = translation.replace('', '\n') + translation = re.sub(r'(__\w+__)', r'\1', translation) + if translation: + current_entry.msgstr_plural[0] = translation + self.logger.debug(f"Updated msgstr[0] for plural entry") + + elif line.startswith('msgstr[1]: '): + if current_entry and current_key == 'msgid_plural': + translation = line[11:].strip() + # Restore newlines and special strings + translation = translation.replace('', '\n') + translation = re.sub(r'(__\w+__)', r'\1', translation) + if translation: + current_entry.msgstr_plural[1] = translation + self.logger.debug(f"Updated msgstr[1] for plural entry") + + self.logger.debug(f"Successfully parsed translated text") + return original_chunk + + except Exception as e: + self.logger.error(f"Error parsing translated text: {str(e)}") + return None + +class TranslationMerger: + def __init__(self, chunks_dir: str, output_file: str, language_code: str): + self.chunks_dir = chunks_dir + self.output_file = output_file + self.language_code = language_code + self.logger = logging.getLogger(__name__) + # Define the locales directory path + self.locales_dir = Path(os.path.dirname(output_file)) / "locales" / language_code / "LC_MESSAGES" + self.locales_dir.mkdir(parents=True, exist_ok=True) + # Load English PO file for reference + self.english_po = polib.pofile(os.path.join(os.path.dirname(output_file), "english.po")) + + def validate_special_strings(self, entry: polib.POEntry, original_entry: polib.POEntry) -> bool: + """Validate that all special strings from the original entry are preserved in the translation.""" + try: + # Extract special strings from original entry with their positions + original_special_strings = [] + for match in re.finditer(r'(__\w+__)', original_entry.msgstr): + original_special_strings.append((match.group(1), match.start())) + + # Extract special strings from translated entry with their positions + translated_special_strings = [] + for match in re.finditer(r'(__\w+__)', entry.msgstr): + translated_special_strings.append((match.group(1), match.start())) + + # Check if we have the same number of special strings + if len(original_special_strings) != len(translated_special_strings): + self.logger.warning(f"Mismatched special strings count for {entry.msgid[:50]}...") + self.logger.warning(f"Original has {len(original_special_strings)} special strings: {[s[0] for s in original_special_strings]}") + self.logger.warning(f"Translation has {len(translated_special_strings)} special strings: {[s[0] for s in translated_special_strings]}") + return False + + # Check if each special string matches and is in a similar relative position + for (orig_str, orig_pos), (trans_str, trans_pos) in zip(original_special_strings, translated_special_strings): + if orig_str != trans_str: + self.logger.warning(f"Mismatched special string in {entry.msgid[:50]}...") + self.logger.warning(f"Original: {orig_str} at position {orig_pos}") + self.logger.warning(f"Translation: {trans_str} at position {trans_pos}") + return False + + # Calculate relative positions (as percentage of total length) + orig_rel_pos = orig_pos / len(original_entry.msgstr) + trans_rel_pos = trans_pos / len(entry.msgstr) + + # Allow some flexibility in position (within 20% of the text length) + if abs(orig_rel_pos - trans_rel_pos) > 0.2: + self.logger.warning(f"Special string {orig_str} is too far from expected position in {entry.msgid[:50]}...") + self.logger.warning(f"Original relative position: {orig_rel_pos:.2f}") + self.logger.warning(f"Translation relative position: {trans_rel_pos:.2f}") + return False + + return True + + except Exception as e: + self.logger.error(f"Error validating special strings: {str(e)}") + return False + + def fix_special_strings(self, entry: polib.POEntry, original_entry: polib.POEntry) -> polib.POEntry: + """Fix missing or misplaced special strings in the translation by copying them from the original entry.""" + try: + # Extract special strings from original entry with their context + original_special_strings = [] + original_text = original_entry.msgstr + translated_text = entry.msgstr + + # Find all special strings and their surrounding context + for match in re.finditer(r'(__\w+__)', original_text): + special_str = match.group(1) + start = max(0, match.start() - 20) # Get 20 chars before + end = min(len(original_text), match.end() + 20) # Get 20 chars after + context = original_text[start:end] + original_special_strings.append((special_str, context, match.start())) + + # For each special string in the original, ensure it exists in the translation + fixed_text = translated_text + for special_str, context, orig_pos in original_special_strings: + # Check if the special string exists in the translation + if special_str not in fixed_text: + # Find a good position to insert the special string + # Try to find similar context in the translation + context_words = set(re.findall(r'\w+', context)) + best_pos = 0 + best_match = 0 + + # Look for similar context in the translation + for i in range(len(fixed_text) - len(context) + 1): + trans_context = fixed_text[i:i + len(context)] + trans_words = set(re.findall(r'\w+', trans_context)) + common_words = len(context_words & trans_words) + if common_words > best_match: + best_match = common_words + best_pos = i + + # Insert the special string at the best position + if best_match > 0: + fixed_text = fixed_text[:best_pos] + special_str + fixed_text[best_pos:] + else: + # If no good context found, append at the end + fixed_text += f"\n{special_str}\n" + + self.logger.info(f"Added missing special string {special_str} to translation") + + # Create a new entry with the fixed translation + fixed_entry = polib.POEntry( + msgid=entry.msgid, + msgstr=fixed_text, + msgid_plural=entry.msgid_plural, + msgstr_plural=entry.msgstr_plural, + comment=entry.comment, + tcomment=entry.tcomment, + occurrences=entry.occurrences, + flags=entry.flags, + previous_msgid=entry.previous_msgid, + previous_msgid_plural=entry.previous_msgid_plural, + encoding=entry.encoding + ) + + # Validate the fix + if not self.validate_special_strings(fixed_entry, original_entry): + self.logger.warning(f"Failed to fix special strings for {entry.msgid[:50]}...") + # If validation fails, return the original entry's msgstr + fixed_entry.msgstr = original_entry.msgstr + self.logger.info(f"Using original English text for {entry.msgid[:50]}...") + + return fixed_entry + + except Exception as e: + self.logger.error(f"Error fixing special strings: {str(e)}") + return entry + + def normalize_po_file(self, po_file: str) -> bool: + """Normalize line endings and validate PO file format.""" + try: + # Read the PO file + with open(po_file, 'r', encoding='utf-8') as f: + content = f.read() + + # Normalize line endings to \n + content = content.replace('\r\n', '\n').replace('\r', '\n') + + # Parse the PO file using polib first to get proper structure + po = polib.pofile(po_file) + + # Create a new PO file with normalized entries + normalized_po = polib.POFile() + normalized_po.metadata = po.metadata.copy() + + for entry in po: + # Create a new entry + new_entry = polib.POEntry( + msgid=entry.msgid.strip(), + msgstr=entry.msgstr.strip(), + msgid_plural=entry.msgid_plural.strip() if entry.msgid_plural else None, + msgstr_plural=entry.msgstr_plural if entry.msgstr_plural else None, + comment=entry.comment, + tcomment=entry.tcomment, + occurrences=entry.occurrences, + flags=entry.flags, + previous_msgid=entry.previous_msgid, + previous_msgid_plural=entry.previous_msgid_plural, + encoding=entry.encoding + ) + normalized_po.append(new_entry) + + # Write back the normalized content + normalized_po.save(po_file) + + # Validate the normalized file + try: + polib.pofile(po_file) + self.logger.info(f"Successfully normalized and validated {po_file}") + return True + except Exception as e: + self.logger.error(f"PO file validation failed: {str(e)}") + return False + + except Exception as e: + self.logger.error(f"Error normalizing PO file: {str(e)}") + return False + + def compile_mo_file(self, po_file: str) -> bool: + """Compile PO file to MO file using msgfmt.""" + try: + # First normalize the PO file + if not self.normalize_po_file(po_file): + self.logger.error(f"Failed to normalize {po_file}") + return False + + # Always use futurecoder.mo as the output filename + mo_file = self.locales_dir / "futurecoder.mo" + + # Use msgfmt to compile the PO file to MO + result = subprocess.run( + ["msgfmt", "-o", str(mo_file), po_file], + capture_output=True, + text=True + ) + + if result.returncode == 0: + self.logger.info(f"Successfully compiled {po_file} to {mo_file}") + return True + else: + self.logger.error(f"Failed to compile {po_file}: {result.stderr}") + return False + + except Exception as e: + self.logger.error(f"Error compiling MO file: {str(e)}") + return False + + def merge_translations(self) -> None: + """Merge translated chunks into a single PO file and compile to MO.""" + self.logger.info(f"Starting merge process for {self.language_code}") + self.logger.info(f"Looking for chunks in: {self.chunks_dir}") + + # Create output directory if it doesn't exist + os.makedirs(os.path.dirname(os.path.abspath(self.output_file)), exist_ok=True) + + # Get all chunk files + chunk_files = sorted(glob.glob(os.path.join(self.chunks_dir, "*.po"))) + if not chunk_files: + self.logger.error(f"No chunk files found in {self.chunks_dir}") + all_files = glob.glob(os.path.join(self.chunks_dir, "*")) + self.logger.info(f"All files found: {all_files}") + raise FileNotFoundError(f"No chunk files found in {self.chunks_dir}") + + self.logger.info(f"Found {len(chunk_files)} chapter-based chunk files to merge") + for f in chunk_files: + self.logger.info(f" - {os.path.basename(f)}") + + # Create new PO file with metadata from english.po + try: + merged_po = polib.POFile() + merged_po.metadata = self.english_po.metadata.copy() + merged_po.metadata['Language'] = self.language_code + + # Get language rules for plural forms + language_rules = Language.get_rules(self.language_code) + merged_po.metadata['Plural-Forms'] = language_rules.plural_forms + except Exception as e: + self.logger.error(f"Failed to read english.po: {str(e)}") + raise + + # Track statistics + total_entries = 0 + translated_entries = 0 + skipped_entries = 0 + code_bits_kept = 0 + program_entries_kept = 0 + prediction_choices_kept = 0 + + # Process each translated chunk + for chunk_file in chunk_files: + self.logger.info(f"Processing translated chunk: {chunk_file}") + try: + chunk_po = polib.pofile(chunk_file) + total_entries += len(chunk_po) + + for entry in chunk_po: + if entry.msgstr and entry.msgstr.strip(): # Only include translated entries + # Find the corresponding English entry + original_entry = self.english_po.find(entry.msgid) + if original_entry: + # For Chinese and Tamil, keep certain entries in English + if self.language_code in ["zh", "ta"] and ( + entry.msgid.startswith("code_bits.") or + entry.msgid.endswith(".program") or + "output_prediction_choices" in entry.msgid + ): + entry.msgstr = original_entry.msgstr # Use English version + if entry.msgid.startswith("code_bits."): + code_bits_kept += 1 + self.logger.info(f"Keeping English code bit: {entry.msgid[:50]}...") + elif entry.msgid.endswith(".program"): + program_entries_kept += 1 + self.logger.info(f"Keeping English program entry: {entry.msgid[:50]}...") + else: + prediction_choices_kept += 1 + self.logger.info(f"Keeping English prediction choice: {entry.msgid[:50]}...") + + # Create a new entry with stripped content + new_entry = polib.POEntry( + msgid=entry.msgid.strip(), + msgstr=entry.msgstr.strip(), + msgid_plural=entry.msgid_plural.strip() if entry.msgid_plural else None, + msgstr_plural=entry.msgstr_plural if entry.msgstr_plural else None, + comment=entry.comment, + tcomment=entry.tcomment, + occurrences=entry.occurrences, + flags=entry.flags, + previous_msgid=entry.previous_msgid, + previous_msgid_plural=entry.previous_msgid_plural, + encoding=entry.encoding + ) + merged_po.append(new_entry) + translated_entries += 1 + else: + self.logger.warning(f"Skipping untranslated entry in {chunk_file}: {entry.msgid[:50]}...") + skipped_entries += 1 + + except Exception as e: + self.logger.error(f"Error processing chunk {chunk_file}: {str(e)}") + raise + + # Save the merged PO file + try: + # Save with proper formatting + merged_po.save(self.output_file) + self.logger.info(f"Successfully merged translations to {self.output_file}") + + # Normalize and compile the merged PO file to MO + if self.compile_mo_file(self.output_file): + self.logger.info(f"Successfully compiled MO file to {self.locales_dir}") + else: + self.logger.error("Failed to compile MO file") + + self.logger.info(f"Statistics:") + self.logger.info(f" Total entries: {total_entries}") + self.logger.info(f" Translated entries: {translated_entries}") + if self.language_code in ["zh", "ta"]: + self.logger.info(f" Code bits kept in English: {code_bits_kept}") + self.logger.info(f" Program entries kept in English: {program_entries_kept}") + self.logger.info(f" Prediction choices kept in English: {prediction_choices_kept}") + self.logger.info(f" Skipped entries: {skipped_entries}") + if total_entries > 0: + self.logger.info(f" Translation coverage: {(translated_entries/total_entries)*100:.1f}%") + except Exception as e: + self.logger.error(f"Failed to save merged file: {str(e)}") + raise + +def validate_language_code(language_code: str) -> bool: + """Validate if the language code is supported""" + try: + Language(language_code) + return True + except ValueError: + return False + +def translate_all_chunks(translator: Translator, base_chunks_dir: str, language_code: str, max_workers: int = 3): + """Translate all chunks from chunks/en/ to chunks/{lang}/, skipping already translated ones.""" + logger = logging.getLogger(__name__) + + en_chunks_dir = os.path.join(base_chunks_dir, "chunks", "en") + target_chunks_dir = os.path.join(base_chunks_dir, "chunks", language_code) + + # Get all English chunk files + en_chunk_files = sorted(glob.glob(os.path.join(en_chunks_dir, "*.po"))) + if not en_chunk_files: + logger.error(f"No English chunk files found in {en_chunks_dir}") + return + + logger.info(f"Found {len(en_chunk_files)} English chunk files in {en_chunks_dir}") + logger.info(f"Will translate to {target_chunks_dir}") + + # Create target directory + os.makedirs(target_chunks_dir, exist_ok=True) + + # Check which chunks need translation + chunks_to_translate = [] + already_translated = [] + + for en_chunk_file in en_chunk_files: + chunk_name = os.path.basename(en_chunk_file) + target_chunk_file = os.path.join(target_chunks_dir, chunk_name) + + if os.path.exists(target_chunk_file) and translator.is_chunk_translated(target_chunk_file): + already_translated.append((en_chunk_file, target_chunk_file)) + else: + chunks_to_translate.append((en_chunk_file, target_chunk_file)) + + logger.info(f"Translation status:") + logger.info(f" - Already translated: {len(already_translated)} chunks") + logger.info(f" - Need translation: {len(chunks_to_translate)} chunks") + + if already_translated: + logger.info("Already translated chunks:") + for en_file, target_file in already_translated: + logger.info(f" ✓ {os.path.basename(target_file)}") + + if not chunks_to_translate: + logger.info("All chunks are already translated! Skipping translation phase.") + return + + logger.info("Chunks to translate:") + for en_file, target_file in chunks_to_translate: + logger.info(f" → {os.path.basename(en_file)} → {os.path.basename(target_file)}") + + # Translate only the chunks that need translation + logger.info(f"Starting translation of {len(chunks_to_translate)} chunks using {max_workers} workers...") + + with ThreadPoolExecutor(max_workers=max_workers) as executor: + # Submit translation tasks + future_to_chunk = { + executor.submit(translator.translate_chunk, en_file, target_file): (en_file, target_file) + for en_file, target_file in chunks_to_translate + } + + completed = 0 + failed = 0 + + # Process completed tasks + for future in as_completed(future_to_chunk): + en_file, target_file = future_to_chunk[future] + try: + result = future.result() + if result is not None: + completed += 1 + logger.info(f"Progress: {completed + failed}/{len(chunks_to_translate)} - Completed: {os.path.basename(target_file)}") + else: + failed += 1 + logger.error(f"Progress: {completed + failed}/{len(chunks_to_translate)} - Failed: {os.path.basename(target_file)}") + except Exception as e: + failed += 1 + logger.error(f"Progress: {completed + failed}/{len(chunks_to_translate)} - Error: {str(e)}") + + logger.info(f"Translation completed: {completed} successful, {failed} failed") + +def main(): + parser = argparse.ArgumentParser(description="Translate Futurecoder PO files") + parser.add_argument("-l", "--language", required=True, help="Language code (e.g., zh, fr, es)") + parser.add_argument("-k", "--api-key", required=True, help="API key for translation service") + parser.add_argument("--base-url", default="https://api.openai.com/v1/chat/completions", + help="Base URL for the translation API") + parser.add_argument("-m", "--model", default="gpt-3.5-turbo", + help="Model to use for translation") + parser.add_argument("-i", "--input", default="./english.po", + help="Input PO file to translate") + parser.add_argument("-o", "--output-dir", default="./", + help="Output directory for translated files") + parser.add_argument("--max-workers", type=int, default=5, + help="Maximum number of parallel workers") + parser.add_argument("--chunk-size", type=int, default=50, + help="Number of entries per chunk") + parser.add_argument("--skip-mo", action="store_true", + help="Skip MO file compilation") + args = parser.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(f"translation_{args.language}.log"), + logging.StreamHandler(sys.stdout) + ] + ) + logger = logging.getLogger(__name__) + + try: + # Validate language code + try: + rules = Language.get_rules(args.language) + logger.info(f"Using translation rules for {rules.language_name}") + except ValueError as e: + logger.error(str(e)) + logger.info("Supported languages: " + ", ".join(lang.value.language_name for lang in Language)) + sys.exit(1) + + # Create base chunks directory structure + base_chunks_dir = args.output_dir + en_chunks_dir = os.path.join(base_chunks_dir, "chunks", "en") + target_chunks_dir = os.path.join(base_chunks_dir, "chunks", args.language) + + logger.info(f"Directory structure:") + logger.info(f" - English chunks: {en_chunks_dir}") + logger.info(f" - Target chunks: {target_chunks_dir}") + + # Initialize components + config = TranslationConfig( + api_key=args.api_key, + base_url=args.base_url, + model=args.model + ) + + # Initialize splitter with base output directory + splitter = POFileSplitter( + input_file=args.input, + base_output_dir=base_chunks_dir, + chunk_size=args.chunk_size + ) + translator = Translator(config, args.language) + merger = TranslationMerger( + chunks_dir=target_chunks_dir, + output_file=os.path.join(args.output_dir, f"{args.language}.po"), + language_code=args.language + ) + + # Split the file into English chunks + logger.info(f"Splitting PO file from: {args.input}") + splitter.split_entries() + + # Translate chunks from en/ to {lang}/ + logger.info("Starting translation of chunks...") + translate_all_chunks(translator, base_chunks_dir, args.language, args.max_workers) + + # Merge translations and compile MO file + logger.info(f"Merging translated chunks to: {merger.output_file}") + merger.merge_translations() + + logger.info("Translation process completed successfully!") + logger.info(f"Final output files:") + logger.info(f" - PO file: {os.path.abspath(merger.output_file)}") + logger.info(f" - MO file: {os.path.abspath(merger.locales_dir / 'futurecoder.mo')}") + + except Exception as e: + logger.error(f"Translation process failed: {str(e)}", exc_info=True) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file