126 lines
4.3 KiB
Python
126 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Диагностический квиз: C/C++, алгоритмы, Linux, сети.
|
|
|
|
Режимы:
|
|
python3 quiz.py — пройти интерактивно (по одной строке на ответ: номер варианта 1-4)
|
|
python3 quiz.py --export — вывести вопросы текстом (можно отвечать в чате в формате "1-2 2-4 ...")
|
|
python3 quiz.py --answers "1-2 2-4 3-1" — проверить ответы, переданные строкой
|
|
Результат пишется в results_quiz.json (там же разбор по доменам).
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
QUIZ = os.path.join(HERE, "quiz.json")
|
|
|
|
|
|
def load():
|
|
with open(QUIZ, encoding="utf-8") as f:
|
|
return json.load(f)
|
|
|
|
|
|
def export(data):
|
|
for i, q in enumerate(data["questions"], 1):
|
|
print(f"{i}. [{data['meta']['domains'][q['d']]}] {q['q']}")
|
|
for j, o in enumerate(q["o"], 1):
|
|
print(f" {j}) {o}")
|
|
print()
|
|
print('Формат ответа: "1-2 2-4 3-1 ..." (номер вопроса - номер варианта)')
|
|
|
|
|
|
def parse_answers(s):
|
|
res = {}
|
|
for tok in s.replace(",", " ").split():
|
|
if "-" not in tok:
|
|
continue
|
|
k, v = tok.split("-", 1)
|
|
try:
|
|
res[int(k)] = int(v)
|
|
except ValueError:
|
|
continue
|
|
return res
|
|
|
|
|
|
def grade(data, answers):
|
|
per_domain = {}
|
|
details = []
|
|
for i, q in enumerate(data["questions"], 1):
|
|
d = q["d"]
|
|
per_domain.setdefault(d, {"total": 0, "correct": 0})
|
|
per_domain[d]["total"] += 1
|
|
got = answers.get(i)
|
|
ok = got == q["a"] + 1
|
|
if ok:
|
|
per_domain[d]["correct"] += 1
|
|
details.append({
|
|
"n": i, "domain": d, "question": q["q"],
|
|
"your_answer": got, "correct_answer": q["a"] + 1,
|
|
"ok": ok, "explain": q["e"],
|
|
})
|
|
return per_domain, details
|
|
|
|
|
|
def report(data, per_domain, details):
|
|
total = len(details)
|
|
correct = sum(1 for x in details if x["ok"])
|
|
print(f"\n=== ИТОГ КВИЗА: {correct}/{total} ===")
|
|
for d, st in per_domain.items():
|
|
pct = round(100 * st["correct"] / st["total"])
|
|
if pct >= 80:
|
|
verdict = "крепко"
|
|
elif pct >= 60:
|
|
verdict = "база есть, нужен добор"
|
|
else:
|
|
verdict = "дыра, идёт в план с нуля"
|
|
print(f" {data['meta']['domains'][d]:38s} {st['correct']}/{st['total']} ({pct}%) — {verdict}")
|
|
wrong = [x for x in details if not x["ok"]]
|
|
if wrong:
|
|
print("\nРазбор промахов:")
|
|
for x in wrong:
|
|
print(f" {x['n']}. {x['question']}")
|
|
print(f" ты: {x['your_answer'] or '—'} | верно: {x['correct_answer']}. {x['explain']}")
|
|
return correct, total
|
|
|
|
|
|
def main():
|
|
data = load()
|
|
args = sys.argv[1:]
|
|
if "--export" in args:
|
|
export(data)
|
|
return
|
|
if "--answers" in args:
|
|
s = args[args.index("--answers") + 1]
|
|
answers = parse_answers(s)
|
|
else:
|
|
answers = {}
|
|
for i, q in enumerate(data["questions"], 1):
|
|
print(f"\n{i}. [{data['meta']['domains'][q['d']]}] {q['q']}")
|
|
for j, o in enumerate(q["o"], 1):
|
|
print(f" {j}) {o}")
|
|
while True:
|
|
raw = input("ответ (1-4, пусто = пропустить, q = выход): ").strip().lower()
|
|
if raw == "q":
|
|
break
|
|
if raw == "":
|
|
break
|
|
if raw in {"1", "2", "3", "4"}:
|
|
answers[i] = int(raw)
|
|
break
|
|
if raw == "q":
|
|
break
|
|
per_domain, details = grade(data, answers)
|
|
correct, total = report(data, per_domain, details)
|
|
out = {
|
|
"correct": correct, "total": total,
|
|
"per_domain": per_domain,
|
|
"details": details,
|
|
}
|
|
with open(os.path.join(HERE, "results_quiz.json"), "w", encoding="utf-8") as f:
|
|
json.dump(out, f, ensure_ascii=False, indent=2)
|
|
print(f"\nРезультат сохранён: {os.path.join(HERE, 'results_quiz.json')}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|