Created
January 3, 2020 15:35
-
-
Save peacememories/a16c4a0d65adf9886fd54d220580391c to your computer and use it in GitHub Desktop.
Example of clingo symbol conversion.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use clingo::{Control, MModel, Part, Symbol}; | |
use std::collections::HashMap; | |
use failure::{err_msg, Error, Fail}; | |
use std::convert::{TryFrom, TryInto}; | |
pub type Locale = String; | |
pub type Names = HashMap<Locale, String>; | |
#[derive(Clone, Debug)] | |
pub enum CurriculumType { | |
Bsc, | |
Msc, | |
Phd, | |
} | |
#[derive(Debug)] | |
pub struct Curriculum { | |
pub id: String, | |
pub names: Names, | |
pub type_: CurriculumType, | |
pub exam_groups: Vec<ExamGroup>, | |
} | |
#[derive(Debug, Serialize)] | |
pub struct ExamGroup { | |
pub id: String, | |
pub names: Names, | |
pub modules: Vec<Module>, | |
} | |
#[derive(Clone, Debug)] | |
pub enum ModuleType { | |
Mandatory, | |
Elective, | |
} | |
#[derive(Debug)] | |
pub struct Module { | |
pub id: String, | |
pub names: Names, | |
pub type_: ModuleType, | |
pub min_ec: CentiEc, | |
pub courses: Vec<Course>, | |
} | |
#[derive(Clone, Debug)] | |
pub enum CourseType { | |
VU, | |
UE, | |
VO, | |
PR, | |
SE, | |
} | |
#[derive(Debug)] | |
pub struct Course { | |
pub id: String, | |
pub names: Names, | |
pub ec: CentiEc, | |
pub type_: CourseType, | |
} | |
pub type CentiEc = u16; | |
impl TryFrom<&Symbol> for CurriculumType { | |
type Error = Error; | |
fn try_from(from: &Symbol) -> Result<Self, Self::Error> { | |
match from.name()? { | |
"bsc" => Ok(Self::Bsc), | |
"msc" => Ok(Self::Msc), | |
"phd" => Ok(Self::Phd), | |
_ => Err(err_msg(format!( | |
"Unexpected curriculum type: {}", | |
from.name()? | |
))), | |
} | |
} | |
} | |
impl TryFrom<&Symbol> for ModuleType { | |
type Error = Error; | |
fn try_from(from: &Symbol) -> Result<Self, Self::Error> { | |
match from.name()? { | |
"mandatory" => Ok(Self::Mandatory), | |
"elective" => Ok(Self::Elective), | |
_ => Err(err_msg("Unexpected module type")), | |
} | |
} | |
} | |
impl TryFrom<&Symbol> for CourseType { | |
type Error = Error; | |
fn try_from(from: &Symbol) -> Result<Self, Self::Error> { | |
match from.name()? { | |
"ctype_VO" => Ok(Self::VO), | |
"ctype_UE" => Ok(Self::UE), | |
"ctype_VU" => Ok(Self::VU), | |
"ctype_PR" => Ok(Self::PR), | |
"ctype_SE" => Ok(Self::SE), | |
_ => Err(err_msg(format!("Unexpected course type: {}", from.name()?))), | |
} | |
} | |
} | |
enum ResSym { | |
Curriculum { | |
key: String, | |
id: String, | |
}, | |
CurriculumType { | |
key: String, | |
type_: CurriculumType, | |
}, | |
CurriculumName { | |
key: String, | |
lang: String, | |
string: String, | |
}, | |
ExamGroup { | |
key: String, | |
}, | |
ExamGroupName { | |
key: String, | |
lang: String, | |
string: String, | |
}, | |
PartOfCurriculum { | |
exam_group: String, | |
curriculum: String, | |
}, | |
Module { | |
key: String, | |
}, | |
ModuleName { | |
key: String, | |
lang: String, | |
string: String, | |
}, | |
PartOfExamgroup { | |
module: String, | |
exam_group: String, | |
}, | |
ModuleType { | |
key: String, | |
type_: ModuleType, | |
}, | |
ModuleMinEc { | |
key: String, | |
ects: CentiEc, | |
}, | |
Course { | |
key: String, | |
}, | |
CourseEc { | |
key: String, | |
ects: CentiEc, | |
}, | |
CourseType { | |
key: String, | |
type_: CourseType, | |
}, | |
PartOfModule { | |
course: String, | |
module: String, | |
}, | |
CourseName { | |
key: String, | |
lang: String, | |
string: String, | |
}, | |
} | |
#[derive(Debug)] | |
enum ResSymError { | |
NotRecognized, | |
Nested(Error), | |
} | |
impl From<Error> for ResSymError { | |
fn from(from: Error) -> Self { | |
Self::Nested(from) | |
} | |
} | |
impl From<clingo::ClingoError> for ResSymError { | |
fn from(from: clingo::ClingoError) -> Self { | |
Self::Nested(from.into()) | |
} | |
} | |
impl Display for ResSymError { | |
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { | |
match self { | |
Self::NotRecognized => write!(f, "Unrecognized symbol"), | |
Self::Nested(error) => error.fmt(f), | |
} | |
} | |
} | |
impl Fail for ResSymError {} | |
impl TryFrom<&Symbol> for ResSym { | |
type Error = ResSymError; | |
fn try_from(symbol: &Symbol) -> Result<Self, Self::Error> { | |
use ResSym::*; | |
let arguments = symbol.arguments()?; | |
match symbol.name()? { | |
"curriculum" => Ok(Curriculum { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
id: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.string()? | |
.into(), | |
}), | |
"curriculum_name" => Ok(CurriculumName { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
lang: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
string: arguments | |
.get(2) | |
.ok_or(err_msg("Not enough arguments"))? | |
.string()? | |
.into(), | |
}), | |
"curriculum_type" => Ok(CurriculumType { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
type_: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.try_into()?, | |
}), | |
"examgroup" => Ok(ExamGroup { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
}), | |
"examgroup_name" => Ok(ExamGroupName { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
lang: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
string: arguments | |
.get(2) | |
.ok_or(err_msg("Not enough arguments"))? | |
.string()? | |
.into(), | |
}), | |
"part_of_curriculum" => Ok(PartOfCurriculum { | |
exam_group: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
curriculum: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
}), | |
"module" => Ok(Module { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
}), | |
"module_name" => Ok(ModuleName { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
lang: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
string: arguments | |
.get(2) | |
.ok_or(err_msg("Not enough arguments"))? | |
.string()? | |
.into(), | |
}), | |
"part_of_examgroup" => Ok(PartOfExamgroup { | |
module: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
exam_group: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
}), | |
"module_type" => Ok(ModuleType { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
type_: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.try_into()?, | |
}), | |
"module_min_cects" => Ok(ModuleMinEc { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
ects: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.number()? as u16, | |
}), | |
"course" => Ok(Course { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
}), | |
"course_cects" => Ok(CourseEc { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
ects: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.number()? as u16, | |
}), | |
"course_type" => Ok(CourseType { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
type_: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.try_into()?, | |
}), | |
"part_of_module" => Ok(PartOfModule { | |
course: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
module: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
}), | |
"course_name" => Ok(CourseName { | |
key: arguments | |
.get(0) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
lang: arguments | |
.get(1) | |
.ok_or(err_msg("Not enough arguments"))? | |
.name()? | |
.into(), | |
string: arguments | |
.get(2) | |
.ok_or(err_msg("Not enough arguments"))? | |
.string()? | |
.into(), | |
}), | |
_ => Err(ResSymError::NotRecognized), | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment