practicode 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +39 -100
- package/THIRD_PARTY_LICENSES.md +58 -0
- package/docs/CONTRIBUTING.md +76 -0
- package/package.json +4 -2
- package/scripts/release.sh +69 -0
- package/src/core.rs +271 -32
- package/src/tui.rs +363 -60
package/src/core.rs
CHANGED
|
@@ -10,7 +10,7 @@ use std::{
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
pub const LANGUAGES: &[&str] = &["python", "ts", "java", "rust"];
|
|
13
|
-
pub const UI_LANGUAGES: &[&str] = &["ko", "
|
|
13
|
+
pub const UI_LANGUAGES: &[&str] = &["en", "ko", "ja", "zh", "es"];
|
|
14
14
|
pub const THEMES: &[&str] = &["dark", "light"];
|
|
15
15
|
pub const AI_PROVIDERS: &[&str] = &["codex", "claude"];
|
|
16
16
|
pub const BANK_PATH: &str = ".practicode/problem_bank.json";
|
|
@@ -120,7 +120,7 @@ pub fn default_language() -> String {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
pub fn default_ui_language() -> String {
|
|
123
|
-
"
|
|
123
|
+
"en".to_string()
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
pub fn default_theme() -> String {
|
|
@@ -163,20 +163,34 @@ pub fn starter_problem() -> Problem {
|
|
|
163
163
|
slug: "hello-world".to_string(),
|
|
164
164
|
difficulty: "easy".to_string(),
|
|
165
165
|
topics: vec!["io".to_string()],
|
|
166
|
-
title:
|
|
167
|
-
|
|
168
|
-
"ko",
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
),
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
"ko",
|
|
176
|
-
"`Hello, World!`
|
|
177
|
-
"
|
|
178
|
-
"
|
|
179
|
-
),
|
|
166
|
+
title: localized_map(&[
|
|
167
|
+
("en", "Hello World"),
|
|
168
|
+
("ko", "Hello World"),
|
|
169
|
+
("ja", "Hello World"),
|
|
170
|
+
("zh", "Hello World"),
|
|
171
|
+
("es", "Hello World"),
|
|
172
|
+
]),
|
|
173
|
+
statement: localized_map(&[
|
|
174
|
+
("en", "Print exactly `Hello, World!` to stdout."),
|
|
175
|
+
("ko", "표준 출력으로 정확히 `Hello, World!`를 출력하세요."),
|
|
176
|
+
("ja", "標準出力に正確に `Hello, World!` を出力してください。"),
|
|
177
|
+
("zh", "向标准输出准确打印 `Hello, World!`。"),
|
|
178
|
+
("es", "Imprime exactamente `Hello, World!` en stdout."),
|
|
179
|
+
]),
|
|
180
|
+
input: localized_map(&[
|
|
181
|
+
("en", "No input."),
|
|
182
|
+
("ko", "입력은 없습니다."),
|
|
183
|
+
("ja", "入力はありません。"),
|
|
184
|
+
("zh", "没有输入。"),
|
|
185
|
+
("es", "No hay entrada."),
|
|
186
|
+
]),
|
|
187
|
+
output: localized_map(&[
|
|
188
|
+
("en", "One line: `Hello, World!`"),
|
|
189
|
+
("ko", "`Hello, World!` 한 줄"),
|
|
190
|
+
("ja", "1行: `Hello, World!`"),
|
|
191
|
+
("zh", "一行: `Hello, World!`"),
|
|
192
|
+
("es", "Una linea: `Hello, World!`"),
|
|
193
|
+
]),
|
|
180
194
|
examples: vec![IoCase {
|
|
181
195
|
input: String::new(),
|
|
182
196
|
output: "Hello, World!\n".to_string(),
|
|
@@ -210,6 +224,13 @@ pub fn map2(k1: &str, v1: &str, k2: &str, v2: &str) -> HashMap<String, String> {
|
|
|
210
224
|
])
|
|
211
225
|
}
|
|
212
226
|
|
|
227
|
+
pub fn localized_map(entries: &[(&str, &str)]) -> HashMap<String, String> {
|
|
228
|
+
entries
|
|
229
|
+
.iter()
|
|
230
|
+
.map(|(key, value)| ((*key).to_string(), (*value).to_string()))
|
|
231
|
+
.collect()
|
|
232
|
+
}
|
|
233
|
+
|
|
213
234
|
pub fn load_bank(root: &Path) -> Result<Vec<Problem>> {
|
|
214
235
|
let path = root.join(BANK_PATH);
|
|
215
236
|
if path.exists() {
|
|
@@ -339,9 +360,7 @@ pub fn save_state(root: &Path, state: &AppState) -> Result<()> {
|
|
|
339
360
|
|
|
340
361
|
pub fn normalize_settings(settings: &mut Settings) {
|
|
341
362
|
settings.language = normalize_language(&settings.language);
|
|
342
|
-
|
|
343
|
-
settings.ui_language = "ko".to_string();
|
|
344
|
-
}
|
|
363
|
+
settings.ui_language = normalize_ui_language(&settings.ui_language);
|
|
345
364
|
if !THEMES.contains(&settings.theme.as_str()) {
|
|
346
365
|
settings.theme = "dark".to_string();
|
|
347
366
|
}
|
|
@@ -364,6 +383,20 @@ pub fn normalize_language(language: &str) -> String {
|
|
|
364
383
|
}
|
|
365
384
|
}
|
|
366
385
|
|
|
386
|
+
pub fn normalize_ui_language(language: &str) -> String {
|
|
387
|
+
let lower = language.trim().to_lowercase();
|
|
388
|
+
let short = lower
|
|
389
|
+
.split(['-', '_'])
|
|
390
|
+
.next()
|
|
391
|
+
.filter(|value| !value.is_empty())
|
|
392
|
+
.unwrap_or("en");
|
|
393
|
+
if UI_LANGUAGES.contains(&short) {
|
|
394
|
+
short.to_string()
|
|
395
|
+
} else {
|
|
396
|
+
default_ui_language()
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
367
400
|
pub fn normalize_next_source(source: &str) -> String {
|
|
368
401
|
if source == "ai" {
|
|
369
402
|
"ai".to_string()
|
|
@@ -381,14 +414,216 @@ pub fn normalize_ai_provider(provider: &str) -> String {
|
|
|
381
414
|
}
|
|
382
415
|
|
|
383
416
|
pub fn localized(map: &HashMap<String, String>, lang: &str) -> String {
|
|
384
|
-
|
|
385
|
-
|
|
417
|
+
let lang = normalize_ui_language(lang);
|
|
418
|
+
map.get(lang.as_str())
|
|
386
419
|
.or_else(|| map.get("en"))
|
|
420
|
+
.or_else(|| map.get("ko"))
|
|
387
421
|
.or_else(|| map.values().next())
|
|
388
422
|
.cloned()
|
|
389
423
|
.unwrap_or_default()
|
|
390
424
|
}
|
|
391
425
|
|
|
426
|
+
pub fn ui_text(lang: &str, key: &str) -> &'static str {
|
|
427
|
+
let lang = normalize_ui_language(lang);
|
|
428
|
+
match (lang.as_str(), key) {
|
|
429
|
+
("ko", "problem") => "문제",
|
|
430
|
+
("ko", "output") => "출력",
|
|
431
|
+
("ko", "command") => "명령",
|
|
432
|
+
("ko", "commands") => "명령",
|
|
433
|
+
("ko", "difficulty") => "난이도",
|
|
434
|
+
("ko", "topics") => "주제",
|
|
435
|
+
("ko", "input") => "입력",
|
|
436
|
+
("ko", "examples") => "예시",
|
|
437
|
+
("ko", "example") => "예시",
|
|
438
|
+
("ko", "command_placeholder") => "/ 입력 후 ↑/↓로 선택, Enter 실행",
|
|
439
|
+
("ko", "palette_hint") => "↑/↓ 선택 | Enter 실행 | Esc 취소",
|
|
440
|
+
("ko", "hint_command") => "Enter 실행 | Esc 취소",
|
|
441
|
+
("ko", "hint_list") => "↑/↓ 이동 | Enter 열기 | Esc 닫기",
|
|
442
|
+
("ko", "hint_output") => "Esc 코드 | / 명령 | ? 도움말",
|
|
443
|
+
("ko", "hint_code") => "Esc 후 / 명령",
|
|
444
|
+
("ko", "hint_idle") => "/ 명령 | ? 도움말",
|
|
445
|
+
("ko", "help_title") => "도움말",
|
|
446
|
+
("ko", "daily_loop") => "기본 흐름",
|
|
447
|
+
("ko", "keys") => "키",
|
|
448
|
+
("ko", "debug_prints") => "디버그 출력",
|
|
449
|
+
("ko", "cmd_run") => "현재 제출을 채점",
|
|
450
|
+
("ko", "cmd_edit") => "코드 편집기로 돌아가기",
|
|
451
|
+
("ko", "cmd_next") => "다음 문제 열기",
|
|
452
|
+
("ko", "cmd_prev") => "이전 문제 열기",
|
|
453
|
+
("ko", "cmd_list") => "문제 목록 열기",
|
|
454
|
+
("ko", "cmd_open") => "번호, id, slug로 문제 열기",
|
|
455
|
+
("ko", "cmd_giveup") => "정답 보기",
|
|
456
|
+
("ko", "cmd_ai") => "현재 문제와 코드에 대해 AI에게 질문",
|
|
457
|
+
("ko", "cmd_provider") => "AI provider 설정",
|
|
458
|
+
("ko", "cmd_model") => "AI model 설정",
|
|
459
|
+
("ko", "cmd_note") => "다음 문제 생성 메모 추가",
|
|
460
|
+
("ko", "cmd_notes") => "저장된 메모 보기",
|
|
461
|
+
("ko", "cmd_lang") => "코드 언어 설정",
|
|
462
|
+
("ko", "cmd_ui") => "UI 언어 설정",
|
|
463
|
+
("ko", "cmd_theme") => "테마 설정",
|
|
464
|
+
("ko", "cmd_source") => "다음 문제 출처 설정",
|
|
465
|
+
("ko", "cmd_exit") => "종료",
|
|
466
|
+
("ko", "cmd_help") => "도움말 열기",
|
|
467
|
+
|
|
468
|
+
("ja", "problem") => "問題",
|
|
469
|
+
("ja", "output") => "出力",
|
|
470
|
+
("ja", "command") => "コマンド",
|
|
471
|
+
("ja", "commands") => "コマンド",
|
|
472
|
+
("ja", "difficulty") => "難易度",
|
|
473
|
+
("ja", "topics") => "トピック",
|
|
474
|
+
("ja", "input") => "入力",
|
|
475
|
+
("ja", "examples") => "例",
|
|
476
|
+
("ja", "example") => "例",
|
|
477
|
+
("ja", "command_placeholder") => "/ を入力し ↑/↓ で選択、Enter で実行",
|
|
478
|
+
("ja", "palette_hint") => "↑/↓ 選択 | Enter 実行 | Esc キャンセル",
|
|
479
|
+
("ja", "hint_command") => "Enter 実行 | Esc キャンセル",
|
|
480
|
+
("ja", "hint_list") => "↑/↓ 移動 | Enter 開く | Esc 閉じる",
|
|
481
|
+
("ja", "hint_output") => "Esc コード | / コマンド | ? ヘルプ",
|
|
482
|
+
("ja", "hint_code") => "Esc の後 / コマンド",
|
|
483
|
+
("ja", "hint_idle") => "/ コマンド | ? ヘルプ",
|
|
484
|
+
("ja", "help_title") => "ヘルプ",
|
|
485
|
+
("ja", "daily_loop") => "基本フロー",
|
|
486
|
+
("ja", "keys") => "キー",
|
|
487
|
+
("ja", "debug_prints") => "デバッグ出力",
|
|
488
|
+
("ja", "cmd_run") => "現在の提出を判定",
|
|
489
|
+
("ja", "cmd_edit") => "コードエディタに戻る",
|
|
490
|
+
("ja", "cmd_next") => "次の問題を開く",
|
|
491
|
+
("ja", "cmd_prev") => "前の問題を開く",
|
|
492
|
+
("ja", "cmd_list") => "問題一覧を開く",
|
|
493
|
+
("ja", "cmd_open") => "番号、id、slug で問題を開く",
|
|
494
|
+
("ja", "cmd_giveup") => "解答を見る",
|
|
495
|
+
("ja", "cmd_ai") => "現在の問題とコードについて AI に質問",
|
|
496
|
+
("ja", "cmd_provider") => "AI provider を設定",
|
|
497
|
+
("ja", "cmd_model") => "AI model を設定",
|
|
498
|
+
("ja", "cmd_note") => "次の問題生成メモを追加",
|
|
499
|
+
("ja", "cmd_notes") => "保存済みメモを見る",
|
|
500
|
+
("ja", "cmd_lang") => "コード言語を設定",
|
|
501
|
+
("ja", "cmd_ui") => "UI 言語を設定",
|
|
502
|
+
("ja", "cmd_theme") => "テーマを設定",
|
|
503
|
+
("ja", "cmd_source") => "次の問題の取得元を設定",
|
|
504
|
+
("ja", "cmd_exit") => "終了",
|
|
505
|
+
("ja", "cmd_help") => "ヘルプを開く",
|
|
506
|
+
|
|
507
|
+
("zh", "problem") => "题目",
|
|
508
|
+
("zh", "output") => "输出",
|
|
509
|
+
("zh", "command") => "命令",
|
|
510
|
+
("zh", "commands") => "命令",
|
|
511
|
+
("zh", "difficulty") => "难度",
|
|
512
|
+
("zh", "topics") => "主题",
|
|
513
|
+
("zh", "input") => "输入",
|
|
514
|
+
("zh", "examples") => "示例",
|
|
515
|
+
("zh", "example") => "示例",
|
|
516
|
+
("zh", "command_placeholder") => "输入 / 后用 ↑/↓ 选择,Enter 执行",
|
|
517
|
+
("zh", "palette_hint") => "↑/↓ 选择 | Enter 执行 | Esc 取消",
|
|
518
|
+
("zh", "hint_command") => "Enter 执行 | Esc 取消",
|
|
519
|
+
("zh", "hint_list") => "↑/↓ 移动 | Enter 打开 | Esc 关闭",
|
|
520
|
+
("zh", "hint_output") => "Esc 代码 | / 命令 | ? 帮助",
|
|
521
|
+
("zh", "hint_code") => "Esc 后输入 / 命令",
|
|
522
|
+
("zh", "hint_idle") => "/ 命令 | ? 帮助",
|
|
523
|
+
("zh", "help_title") => "帮助",
|
|
524
|
+
("zh", "daily_loop") => "日常流程",
|
|
525
|
+
("zh", "keys") => "按键",
|
|
526
|
+
("zh", "debug_prints") => "调试输出",
|
|
527
|
+
("zh", "cmd_run") => "评测当前提交",
|
|
528
|
+
("zh", "cmd_edit") => "回到代码编辑器",
|
|
529
|
+
("zh", "cmd_next") => "打开下一题",
|
|
530
|
+
("zh", "cmd_prev") => "打开上一题",
|
|
531
|
+
("zh", "cmd_list") => "打开题目列表",
|
|
532
|
+
("zh", "cmd_open") => "按编号、id 或 slug 打开题目",
|
|
533
|
+
("zh", "cmd_giveup") => "显示参考答案",
|
|
534
|
+
("zh", "cmd_ai") => "向 AI 询问当前题目和代码",
|
|
535
|
+
("zh", "cmd_provider") => "设置 AI provider",
|
|
536
|
+
("zh", "cmd_model") => "设置 AI model",
|
|
537
|
+
("zh", "cmd_note") => "添加下次出题备注",
|
|
538
|
+
("zh", "cmd_notes") => "查看保存的备注",
|
|
539
|
+
("zh", "cmd_lang") => "设置代码语言",
|
|
540
|
+
("zh", "cmd_ui") => "设置 UI 语言",
|
|
541
|
+
("zh", "cmd_theme") => "设置主题",
|
|
542
|
+
("zh", "cmd_source") => "设置下一题来源",
|
|
543
|
+
("zh", "cmd_exit") => "退出",
|
|
544
|
+
("zh", "cmd_help") => "打开帮助",
|
|
545
|
+
|
|
546
|
+
("es", "problem") => "Problema",
|
|
547
|
+
("es", "output") => "Salida",
|
|
548
|
+
("es", "command") => "Comando",
|
|
549
|
+
("es", "commands") => "Comandos",
|
|
550
|
+
("es", "difficulty") => "Dificultad",
|
|
551
|
+
("es", "topics") => "Temas",
|
|
552
|
+
("es", "input") => "Entrada",
|
|
553
|
+
("es", "examples") => "Ejemplos",
|
|
554
|
+
("es", "example") => "Ejemplo",
|
|
555
|
+
("es", "command_placeholder") => "Escribe /, elige con ↑/↓, Enter ejecuta",
|
|
556
|
+
("es", "palette_hint") => "↑/↓ elegir | Enter ejecutar | Esc cancelar",
|
|
557
|
+
("es", "hint_command") => "Enter ejecutar | Esc cancelar",
|
|
558
|
+
("es", "hint_list") => "↑/↓ mover | Enter abrir | Esc cerrar",
|
|
559
|
+
("es", "hint_output") => "Esc codigo | / comando | ? ayuda",
|
|
560
|
+
("es", "hint_code") => "Esc y luego / comando",
|
|
561
|
+
("es", "hint_idle") => "/ comando | ? ayuda",
|
|
562
|
+
("es", "help_title") => "Ayuda",
|
|
563
|
+
("es", "daily_loop") => "Flujo diario",
|
|
564
|
+
("es", "keys") => "Teclas",
|
|
565
|
+
("es", "debug_prints") => "Salida de depuracion",
|
|
566
|
+
("es", "cmd_run") => "Evalua la solucion actual",
|
|
567
|
+
("es", "cmd_edit") => "Volver al editor de codigo",
|
|
568
|
+
("es", "cmd_next") => "Abrir el siguiente problema",
|
|
569
|
+
("es", "cmd_prev") => "Abrir el problema anterior",
|
|
570
|
+
("es", "cmd_list") => "Abrir la lista de problemas",
|
|
571
|
+
("es", "cmd_open") => "Abrir por numero, id o slug",
|
|
572
|
+
("es", "cmd_giveup") => "Mostrar la respuesta de referencia",
|
|
573
|
+
("es", "cmd_ai") => "Preguntar a AI sobre el problema y codigo actuales",
|
|
574
|
+
("es", "cmd_provider") => "Configurar AI provider",
|
|
575
|
+
("es", "cmd_model") => "Configurar AI model",
|
|
576
|
+
("es", "cmd_note") => "Agregar nota para generar problemas",
|
|
577
|
+
("es", "cmd_notes") => "Ver notas guardadas",
|
|
578
|
+
("es", "cmd_lang") => "Configurar lenguaje de codigo",
|
|
579
|
+
("es", "cmd_ui") => "Configurar idioma de UI",
|
|
580
|
+
("es", "cmd_theme") => "Configurar tema",
|
|
581
|
+
("es", "cmd_source") => "Configurar fuente del siguiente problema",
|
|
582
|
+
("es", "cmd_exit") => "Salir",
|
|
583
|
+
("es", "cmd_help") => "Abrir ayuda",
|
|
584
|
+
|
|
585
|
+
(_, "problem") => "Problem",
|
|
586
|
+
(_, "output") => "Output",
|
|
587
|
+
(_, "command") => "Command",
|
|
588
|
+
(_, "commands") => "Commands",
|
|
589
|
+
(_, "difficulty") => "Difficulty",
|
|
590
|
+
(_, "topics") => "Topics",
|
|
591
|
+
(_, "input") => "Input",
|
|
592
|
+
(_, "examples") => "Examples",
|
|
593
|
+
(_, "example") => "Example",
|
|
594
|
+
(_, "command_placeholder") => "Type /, move with ↑/↓, Enter runs",
|
|
595
|
+
(_, "palette_hint") => "↑/↓ select | Enter run | Esc cancel",
|
|
596
|
+
(_, "hint_command") => "Enter submit | Esc cancel",
|
|
597
|
+
(_, "hint_list") => "up/down move | Enter open | Esc close",
|
|
598
|
+
(_, "hint_output") => "Esc code | / command | ? help",
|
|
599
|
+
(_, "hint_code") => "Esc then / command",
|
|
600
|
+
(_, "hint_idle") => "/ command | ? help",
|
|
601
|
+
(_, "help_title") => "Help",
|
|
602
|
+
(_, "daily_loop") => "Daily loop",
|
|
603
|
+
(_, "keys") => "Keys",
|
|
604
|
+
(_, "debug_prints") => "Debug prints",
|
|
605
|
+
(_, "cmd_run") => "Judge the current submission",
|
|
606
|
+
(_, "cmd_edit") => "Return to the code editor",
|
|
607
|
+
(_, "cmd_next") => "Open the next problem",
|
|
608
|
+
(_, "cmd_prev") => "Open the previous problem",
|
|
609
|
+
(_, "cmd_list") => "Browse problems",
|
|
610
|
+
(_, "cmd_open") => "Open by number, id, or slug",
|
|
611
|
+
(_, "cmd_giveup") => "Show the reference answer",
|
|
612
|
+
(_, "cmd_ai") => "Ask AI about the current problem and code",
|
|
613
|
+
(_, "cmd_provider") => "Set AI provider",
|
|
614
|
+
(_, "cmd_model") => "Set AI model",
|
|
615
|
+
(_, "cmd_note") => "Add a next-problem note",
|
|
616
|
+
(_, "cmd_notes") => "Show saved notes",
|
|
617
|
+
(_, "cmd_lang") => "Set code language",
|
|
618
|
+
(_, "cmd_ui") => "Set UI language",
|
|
619
|
+
(_, "cmd_theme") => "Set theme",
|
|
620
|
+
(_, "cmd_source") => "Set next-problem source",
|
|
621
|
+
(_, "cmd_exit") => "Quit",
|
|
622
|
+
(_, "cmd_help") => "Open help",
|
|
623
|
+
_ => "",
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
392
627
|
pub fn template_for(language: &str) -> String {
|
|
393
628
|
match normalize_language(language).as_str() {
|
|
394
629
|
"python" => "# Read from stdin and print to stdout.\nimport sys\n\n\n".to_string(),
|
|
@@ -415,20 +650,19 @@ pub fn ensure_submission(root: &Path, problem: &Problem, settings: &Settings) ->
|
|
|
415
650
|
}
|
|
416
651
|
|
|
417
652
|
pub fn render_problem(problem: &Problem, ui_language: &str) -> String {
|
|
418
|
-
let lang =
|
|
419
|
-
ui_language
|
|
420
|
-
} else {
|
|
421
|
-
"ko"
|
|
422
|
-
};
|
|
653
|
+
let lang = normalize_ui_language(ui_language);
|
|
423
654
|
let examples = problem
|
|
424
655
|
.examples
|
|
425
656
|
.iter()
|
|
426
657
|
.enumerate()
|
|
427
658
|
.map(|(index, case)| {
|
|
428
659
|
format!(
|
|
429
|
-
"###
|
|
660
|
+
"### {} {}\n\n{}\n\n{}\n\n{}\n\n{}",
|
|
661
|
+
ui_text(&lang, "example"),
|
|
430
662
|
index + 1,
|
|
663
|
+
ui_text(&lang, "input"),
|
|
431
664
|
fenced_text(&case.input),
|
|
665
|
+
ui_text(&lang, "output"),
|
|
432
666
|
fenced_text(&case.output)
|
|
433
667
|
)
|
|
434
668
|
})
|
|
@@ -440,13 +674,18 @@ pub fn render_problem(problem: &Problem, ui_language: &str) -> String {
|
|
|
440
674
|
.map(|(number, _)| number)
|
|
441
675
|
.unwrap_or(&problem.id);
|
|
442
676
|
format!(
|
|
443
|
-
"# {number}. {}\n\
|
|
444
|
-
localized(&problem.title, lang),
|
|
677
|
+
"# {number}. {}\n\n{}: {}\n{}: {}\n\n{}\n\n## {}\n\n{}\n\n## {}\n\n{}\n\n## {}\n\n{}",
|
|
678
|
+
localized(&problem.title, &lang),
|
|
679
|
+
ui_text(&lang, "difficulty"),
|
|
445
680
|
problem.difficulty,
|
|
681
|
+
ui_text(&lang, "topics"),
|
|
446
682
|
problem.topics.join(", "),
|
|
447
|
-
localized(&problem.statement, lang),
|
|
448
|
-
|
|
449
|
-
localized(&problem.
|
|
683
|
+
localized(&problem.statement, &lang),
|
|
684
|
+
ui_text(&lang, "input"),
|
|
685
|
+
localized(&problem.input, &lang),
|
|
686
|
+
ui_text(&lang, "output"),
|
|
687
|
+
localized(&problem.output, &lang),
|
|
688
|
+
ui_text(&lang, "examples"),
|
|
450
689
|
examples
|
|
451
690
|
)
|
|
452
691
|
}
|