use std::path::Path;
use crate::models::spec::Oracle;
use crate::models::{StudentFile, TestCase, TestSpec};
use crate::runner::python::PythonExecutor;
pub async fn resolve_oracle(
case: &mut TestCase,
oracle: &Oracle,
spec: &TestSpec,
executor: &PythonExecutor,
arg_names: &[String],
) {
if let Some(ref_path) = &oracle.reference {
let ref_file = StudentFile {
path: Path::new(ref_path).to_path_buf(),
language: "python".to_string(),
};
let ref_spec = TestSpec {
meta: spec.meta.clone(),
vars: Default::default(),
setup: vec![],
cases: vec![],
lint: None,
};
let result = executor
.execute_case(&[ref_file], &ref_spec, case, 10)
.await;
if let Some(actual) = &result.actual {
case.expect = serde_json::from_str(actual).ok();
}
} else if let Some(rhai_expr) = &oracle.rhai {
let engine = rhai::Engine::new();
let mut scope = rhai::Scope::new();
for (i, name) in arg_names.iter().enumerate() {
if let Some(val) = case.args.get(i) {
scope.push_dynamic(
name.as_str(),
crate::checker::rhai_checker::json_to_dynamic(val),
);
}
}
if let Ok(result) = engine.eval_with_scope::<rhai::Dynamic>(&mut scope, rhai_expr) {
case.expect = Some(dynamic_to_json(&result));
}
} else if let Some(check_name) = &oracle.check {
case.check = Some(crate::models::CheckMethod::Builtin(check_name.clone()));
}
}
fn dynamic_to_json(val: &rhai::Dynamic) -> serde_json::Value {
if let Ok(b) = val.as_bool() {
serde_json::Value::from(b)
} else if let Ok(i) = val.as_int() {
serde_json::Value::from(i)
} else if let Ok(f) = val.as_float() {
serde_json::Value::from(f)
} else if let Ok(s) = val.clone().into_string() {
serde_json::Value::from(s)
} else {
serde_json::Value::Null
}
}