use crate::coding::catalog::ProgramSpec;
use crate::language::Language;
use crate::solver::{ConversationRole, ConversationTurn};
pub fn history_has_prior_code(history: &[ConversationTurn]) -> bool {
history.iter().any(|turn| {
matches!(turn.role, ConversationRole::Assistant) && turn.content.contains("```")
})
}
pub fn program_explanation_section(spec: ProgramSpec, language: Language) -> String {
let heading = match language {
Language::Russian => "Как это работает:",
Language::Hindi => "यह कैसे काम करता है:",
Language::Chinese => "工作原理:",
_ => "How it works:",
};
format!(
"{heading}\n{}",
program_explanation(spec.task.slug, language)
)
}
fn program_explanation(task_slug: &str, language: Language) -> &'static str {
match (task_slug, language) {
("hello_world", Language::Russian) => {
"Программа выводит текст `Hello, world!` в стандартный вывод и завершается."
}
("hello_world", Language::Hindi) => {
"प्रोग्राम मानक आउटपुट पर `Hello, world!` टेक्स्ट छापता है और फिर समाप्त हो जाता है।"
}
("hello_world", Language::Chinese) => {
"程序将文本 `Hello, world!` 打印到标准输出,然后退出。"
}
("hello_world", _) => {
"The program prints the text `Hello, world!` to standard output and then exits."
}
("count_to_three", Language::Russian) => {
"Программа выводит числа 1, 2 и 3 — каждое на отдельной строке — и завершается."
}
("count_to_three", Language::Hindi) => {
"प्रोग्राम संख्याएँ 1, 2 और 3 — हर एक अलग पंक्ति में — छापता है और फिर समाप्त हो जाता है।"
}
("count_to_three", Language::Chinese) => {
"程序打印数字 1、2 和 3 —— 每个数字单独一行 —— 然后退出。"
}
("count_to_three", _) => {
"The program prints the numbers 1, 2, and 3 — each on its own line — and then exits."
}
("list_files_arg", Language::Russian) => {
"Программа берёт путь к каталогу из первого аргумента командной строки (если \
аргумент не задан, используется текущий каталог), читает содержимое этого \
каталога, оставляет только обычные файлы, сортирует их имена по алфавиту и \
печатает каждое имя на отдельной строке."
}
("list_files_arg", Language::Hindi) => {
"प्रोग्राम पहले कमांड-लाइन तर्क से निर्देशिका पथ लेता है (कोई तर्क न होने पर वर्तमान \
निर्देशिका का उपयोग करता है), उस निर्देशिका की प्रविष्टियाँ पढ़ता है, केवल सामान्य \
फ़ाइलें रखता है, उनके नामों को वर्णानुक्रम में क्रमबद्ध करता है, और हर नाम को अलग पंक्ति \
में छापता है।"
}
("list_files_arg", Language::Chinese) => {
"程序从第一个命令行参数获取目录路径(未提供参数时使用当前目录),读取该目录的条目,\
只保留普通文件,按字母顺序排序它们的名称,然后将每个名称打印在单独一行。"
}
("list_files_arg", _) => {
"The program takes the directory path from the first command-line argument \
(falling back to the current directory when none is given), reads that \
directory's entries, keeps only the regular files, sorts their names \
alphabetically, and prints each name on its own line."
}
("list_files", Language::Russian) => {
"Программа читает содержимое текущего каталога, оставляет только обычные файлы, \
собирает их имена в список, сортирует список по алфавиту и печатает каждое имя \
на отдельной строке."
}
("list_files", Language::Hindi) => {
"प्रोग्राम वर्तमान निर्देशिका की प्रविष्टियाँ पढ़ता है, केवल सामान्य फ़ाइलें रखता है, उनके \
नाम एक सूची में एकत्र करता है, सूची को वर्णानुक्रम में क्रमबद्ध करता है, और हर नाम को \
अलग पंक्ति में छापता है।"
}
("list_files", Language::Chinese) => {
"程序读取当前目录的条目,只保留普通文件,将它们的名称收集到一个列表中,\
按字母顺序排序,然后将每个名称打印在单独一行。"
}
("list_files", _) => {
"The program reads the entries of the current directory, keeps only the regular \
files, collects their names into a list, sorts the list alphabetically, and \
prints each name on its own line."
}
("fizzbuzz", Language::Russian) => {
"Программа перебирает числа от 1 до 15. Для каждого числа она печатает `FizzBuzz`, \
если оно делится и на 3, и на 5; `Fizz`, если делится на 3; `Buzz`, если делится \
на 5; иначе само число — каждое на отдельной строке."
}
("fizzbuzz", Language::Hindi) => {
"प्रोग्राम 1 से 15 तक की संख्याओं पर लूप करता है। हर संख्या के लिए वह `FizzBuzz` छापता है \
जब वह 3 और 5 दोनों से विभाज्य हो, `Fizz` जब वह 3 से विभाज्य हो, `Buzz` जब वह 5 से \
विभाज्य हो, अन्यथा स्वयं संख्या — हर एक अलग पंक्ति में।"
}
("fizzbuzz", Language::Chinese) => {
"程序遍历数字 1 到 15。对于每个数字,当它同时能被 3 和 5 整除时打印 `FizzBuzz`,\
能被 3 整除时打印 `Fizz`,能被 5 整除时打印 `Buzz`,否则打印数字本身 —— 每个单独一行。"
}
("fizzbuzz", _) => {
"The program loops over the numbers 1 to 15. For each number it prints `FizzBuzz` \
when the number is divisible by both 3 and 5, `Fizz` when it is divisible by 3, \
`Buzz` when it is divisible by 5, and otherwise the number itself — each on its \
own line."
}
("factorial", Language::Russian) => {
"Программа перемножает числа от 1 до 5 (1×2×3×4×5) — это факториал 5 — и печатает \
результат, 120."
}
("factorial", Language::Hindi) => {
"प्रोग्राम 1 से 5 तक की संख्याओं को आपस में गुणा करता है (1×2×3×4×5), जो 5 का फैक्टोरियल \
है, और परिणाम 120 छापता है।"
}
("factorial", Language::Chinese) => {
"程序将 1 到 5 的数字相乘(1×2×3×4×5),这就是 5 的阶乘,并打印结果 120。"
}
("factorial", _) => {
"The program multiplies together the numbers 1 through 5 (1×2×3×4×5), which is the \
factorial of 5, and prints the result, 120."
}
("reverse_string", Language::Russian) => {
"Программа берёт строку `hello`, переставляет её символы в обратном порядке и \
печатает результат — `olleh`."
}
("reverse_string", Language::Hindi) => {
"प्रोग्राम स्ट्रिंग `hello` लेता है, उसके अक्षरों का क्रम उलटता है, और परिणाम `olleh` छापता है।"
}
("reverse_string", Language::Chinese) => {
"程序取字符串 `hello`,将其字符顺序反转,并打印结果 `olleh`。"
}
("reverse_string", _) => {
"The program takes the string `hello`, reverses the order of its characters, and \
prints the result, `olleh`."
}
("sum_to_ten", Language::Russian) => {
"Программа складывает целые числа от 1 до 10 (1 + 2 + … + 10) и печатает сумму — 55."
}
("sum_to_ten", Language::Hindi) => {
"प्रोग्राम 1 से 10 तक के पूर्णांकों को जोड़ता है (1 + 2 + … + 10) और कुल योग 55 छापता है।"
}
("sum_to_ten", Language::Chinese) => {
"程序将 1 到 10 的整数相加(1 + 2 + … + 10),并打印总和 55。"
}
("sum_to_ten", _) => {
"The program adds together the integers from 1 to 10 (1 + 2 + … + 10) and prints \
the total, 55."
}
(_, Language::Russian) => {
"Программа выполняет запрошенную задачу и печатает результат в стандартный вывод."
}
(_, Language::Hindi) => "प्रोग्राम अनुरोधित कार्य करता है और परिणाम को मानक आउटपुट पर छापता है।",
(_, Language::Chinese) => "程序执行所请求的任务,并将结果打印到标准输出。",
(_, _) => {
"The program performs the requested task and prints its result to standard output."
}
}
}
pub fn program_test_instructions(
spec: ProgramSpec,
language: Language,
prior_code_response: bool,
) -> String {
let execution = &spec.language.execution;
let save_as = spec.language.save_as;
let run_command = execution.run_command;
if prior_code_response {
return match language {
Language::Russian => format!(
"Проверьте обновлённую программу так же, как и раньше: сохраните код в файл \
`{save_as}` и снова выполните `{run_command}`."
),
Language::Hindi => format!(
"अपडेट किए गए प्रोग्राम को पहले की तरह ही जाँचें: कोड को `{save_as}` फ़ाइल में सहेजें \
और फिर से `{run_command}` चलाएँ।"
),
Language::Chinese => format!(
"像之前一样测试更新后的程序:将代码保存到文件 `{save_as}`,然后再次运行 \
`{run_command}`。"
),
_ => format!(
"Test the updated program the same way as before: save the code to `{save_as}` \
and run `{run_command}` again."
),
};
}
let heading = match language {
Language::Russian => "Как проверить это самостоятельно:",
Language::Hindi => "इसे स्वयं कैसे जाँचें:",
Language::Chinese => "如何自行测试:",
_ => "How to test it yourself:",
};
let mut steps: Vec<String> = Vec::new();
let setup_hint = spec.language.setup_hint;
steps.push(match language {
Language::Russian => format!("Установите инструментарий: {setup_hint}."),
Language::Hindi => format!("टूलचेन इंस्टॉल करें: {setup_hint}।"),
Language::Chinese => format!("安装工具链:{setup_hint}。"),
_ => format!("Install {setup_hint}."),
});
steps.push(match language {
Language::Russian => format!("Сохраните приведённый выше код в файл `{save_as}`."),
Language::Hindi => format!("ऊपर दिए गए कोड को `{save_as}` फ़ाइल में सहेजें।"),
Language::Chinese => format!("将上面的代码保存到文件 `{save_as}`。"),
_ => format!("Save the code above to a file named `{save_as}`."),
});
if let Some(check_command) = execution.check_command {
steps.push(match language {
Language::Russian => format!("Проверьте, что код компилируется: `{check_command}`."),
Language::Hindi => format!("जाँचें कि कोड संकलित होता है: `{check_command}`।"),
Language::Chinese => format!("检查代码能否编译:`{check_command}`。"),
_ => format!("Check that it compiles: `{check_command}`."),
});
}
steps.push(match language {
Language::Russian => format!("Запустите программу: `{run_command}`."),
Language::Hindi => format!("प्रोग्राम चलाएँ: `{run_command}`।"),
Language::Chinese => format!("运行程序:`{run_command}`。"),
_ => format!("Run it: `{run_command}`."),
});
steps.push(match language {
Language::Russian => "Сравните вывод с разделом ожидаемого вывода выше.".to_owned(),
Language::Hindi => "आउटपुट की तुलना ऊपर दिए गए अपेक्षित आउटपुट से करें।".to_owned(),
Language::Chinese => "将输出与上面的预期输出部分进行比较。".to_owned(),
_ => "Compare the output with the expected output shown above.".to_owned(),
});
let numbered = steps
.iter()
.enumerate()
.map(|(index, step)| format!("{}. {step}", index + 1))
.collect::<Vec<_>>()
.join("\n");
format!("{heading}\n{numbered}")
}