problem set generator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mild changes to how questions are structures, somewhat of a proof of concept

+126 -127
+48 -4
Cargo.lock
··· 148 148 149 149 [[package]] 150 150 name = "cc" 151 - version = "1.2.60" 151 + version = "1.2.61" 152 152 source = "registry+https://github.com/rust-lang/crates.io-index" 153 - checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" 153 + checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" 154 154 dependencies = [ 155 155 "find-msvc-tools", 156 156 "shlex", ··· 234 234 checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 235 235 236 236 [[package]] 237 + name = "document-features" 238 + version = "0.2.12" 239 + source = "registry+https://github.com/rust-lang/crates.io-index" 240 + checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" 241 + dependencies = [ 242 + "litrs", 243 + ] 244 + 245 + [[package]] 237 246 name = "dtoa" 238 247 version = "0.4.8" 239 248 source = "registry+https://github.com/rust-lang/crates.io-index" 240 249 checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" 250 + 251 + [[package]] 252 + name = "dyn-fmt" 253 + version = "0.4.3" 254 + source = "registry+https://github.com/rust-lang/crates.io-index" 255 + checksum = "c992f591dfce792a9bc2d1880ab67ffd4acc04551f8e551ca3b6233efb322f00" 256 + dependencies = [ 257 + "document-features", 258 + ] 241 259 242 260 [[package]] 243 261 name = "encoding" ··· 602 620 603 621 [[package]] 604 622 name = "libc" 605 - version = "0.2.185" 623 + version = "0.2.186" 606 624 source = "registry+https://github.com/rust-lang/crates.io-index" 607 - checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" 625 + checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" 608 626 609 627 [[package]] 610 628 name = "linked-hash-map" 611 629 version = "0.5.6" 612 630 source = "registry+https://github.com/rust-lang/crates.io-index" 613 631 checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 632 + 633 + [[package]] 634 + name = "litrs" 635 + version = "1.0.0" 636 + source = "registry+https://github.com/rust-lang/crates.io-index" 637 + checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" 614 638 615 639 [[package]] 616 640 name = "log" ··· 682 706 ] 683 707 684 708 [[package]] 709 + name = "multicalc" 710 + version = "0.5.0" 711 + source = "registry+https://github.com/rust-lang/crates.io-index" 712 + checksum = "251c41662f3a714bd59face911d49a3e07ecb4d106833a55e3a78b432e48ddd5" 713 + dependencies = [ 714 + "num-complex", 715 + ] 716 + 717 + [[package]] 718 + name = "num-complex" 719 + version = "0.4.6" 720 + source = "registry+https://github.com/rust-lang/crates.io-index" 721 + checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 722 + dependencies = [ 723 + "num-traits", 724 + ] 725 + 726 + [[package]] 685 727 name = "num-traits" 686 728 version = "0.2.19" 687 729 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 759 801 version = "0.1.0" 760 802 dependencies = [ 761 803 "axum", 804 + "dyn-fmt", 762 805 "genpdf", 763 806 "hyphenation", 807 + "multicalc", 764 808 "rand", 765 809 "strum", 766 810 "strum_macros",
+2
Cargo.toml
··· 5 5 6 6 [dependencies] 7 7 axum = "0.8.9" 8 + dyn-fmt = "0.4.3" 8 9 genpdf = { version = "0.2.0", features = ["hyphenation"] } 9 10 hyphenation = { version = "0.8.4", features = ["embed_en-us"] } 11 + multicalc = "0.5.0" 10 12 rand = "0.10.1" 11 13 strum = "0.28.0" 12 14 strum_macros = "0.28.0"
-18
problems/Math/PartialDerivatives/3elem.txt
··· 1 - Math; 2 - PartialDerivatives; 3 - 4 - f(x,y) = x^ {{0}} + x^ {{1}} *y^ {{2}} - {{3}} *y^ {{4}} 5 - 6 - f_x( {{5}} , {{6}} ) = ? 7 - f_y( {{7}} , {{8}} ) = ?; 8 - 1,5 9 - 2,5 10 - 2,5 11 - 1,5 12 - 1,5 13 - 1,33 14 - 2,44 15 - 1,33 16 - 2,44; 17 - {{1}} 18 -
+38 -48
src/main.rs
··· 1 - 2 - use std::str::FromStr; 3 1 4 2 use genpdf::fonts::FontData; 5 3 use hyphenation::{Load, Standard}; 6 4 7 5 mod util; 8 - use crate::util::{Question, build_document_base, build_response}; 6 + use crate::util::{build_document_base, build_response}; 7 + 8 + mod problems; 9 9 10 - use axum::{Router, extract::{Path, State}, http::{HeaderMap, header}, response::IntoResponse, routing::get}; 10 + use axum::{Router, extract::{Path, State}, response::IntoResponse, routing::get}; 11 11 12 12 #[derive(Clone)] 13 13 pub struct GenpdfState { ··· 21 21 key: Option<Path<i32>>) 22 22 -> impl IntoResponse { 23 23 24 + let nelem_p = problems::nelem::build_nelem(); 24 25 25 26 let len = match key { 26 27 Some(Path(a)) => a, ··· 29 30 30 31 let mut doc = build_document_base(state); 31 32 32 - let test_string: &str = "Math; 33 - PartialDerivatives; 33 + for i in 0..len { 34 34 35 - f(x,y) = x^ {{0}} + x^ {{1}} *y^ {{2}} - {{3}} *y^ {{4}} 35 + doc.push(genpdf::elements::Text::new(format!("question {i}"))) ; 36 + let (text,answer) = nelem_p.generate_question(); 37 + for l in text.lines() { 38 + doc.push( 39 + genpdf::elements::Text::new( 40 + l 41 + )); 42 + } 36 43 37 - f_x( {{5}} , {{6}} ) = ? 44 + doc.push(genpdf::elements::Text::new("Answer:")); 45 + doc.push(genpdf::elements::Text::new(answer)); 46 + doc.push(genpdf::elements::Text::new("")); 38 47 39 - f_y( {{7}} , {{8}} ) = ?; 40 - 1,5 41 - 2,5 42 - 2,5 43 - 1,5 44 - 1,5 45 - 1,33 46 - 2,44 47 - 1,33 48 - 2,44"; 49 - 50 - let q = Question::from_str(test_string).unwrap(); 51 - 52 - for i in 0..len { 53 - doc.push( 54 - genpdf::elements::Paragraph::new( 55 - // format!("this is line {}", i) 56 - q.generate_question() 57 - )); 58 - } 48 + }; 59 49 60 50 61 51 build_response(doc) ··· 92 82 93 83 94 84 95 - #[test] 96 - fn test_string_to_question_parse() { 97 - let test_question = Question { 98 - subject:util::Subject::Math, 99 - theme:util::Theme::Math(util::MathTheme::ParametricEquations), 100 - text: "\n\n{{0}} + y = 12".to_string(), 101 - var_conditions:vec![(1,4)], 102 - ans_expression: None}; 103 - let test_string: &str = "Math; 104 - ParametricEquations; 105 - 106 - 107 - {{0}} + y = 12; 108 - 1,4"; 109 - 110 - let text = Question::from_str(test_string).unwrap().generate_question(); 111 - println!("{}\n",text); 112 - assert_eq!(Question::from_str(test_string).unwrap(),test_question); 113 - 114 - } 85 + //#[test] 86 + //fn test_string_to_question_parse() { 87 + // let test_question = Question { 88 + // subject:util::Subject::Math, 89 + // theme:util::Theme::Math(util::MathTheme::ParametricEquations), 90 + // text: "\n\n{{0}} + y = 12".to_string(), 91 + // var_conditions:vec![(1,4)], 92 + // ans_expression: None}; 93 + // let test_string: &str = "Math; 94 + //ParametricEquations; 95 + // 96 + // 97 + //{{0}} + y = 12; 98 + //1,4"; 99 + // 100 + // let text = Question::from_str(test_string).unwrap().generate_question(); 101 + // println!("{}\n",text); 102 + // assert_eq!(Question::from_str(test_string).unwrap(),test_question); 103 + // 104 + //}
+1
src/problems/mod.rs
··· 1 + pub mod nelem;
+20
src/problems/nelem.rs
··· 1 + use crate::util::Question; 2 + 3 + //pub static THREE_ELEM:Question<impl Fn(f32, f32) -> f32> = Question { 4 + // 5 + pub fn build_nelem() -> Question<impl Fn(&[f32]) -> f32> { 6 + Question{ 7 + subject: crate::util::Subject::Math, 8 + theme: crate::util::Theme::Math(crate::util::MathTheme::PartialDerivatives), 9 + text: "f(x,y) = x^{} + x^ {} *y^{} - {}*y^{} 10 + 11 + f_x( {} , {} ) = ?\n", 12 + var_conditions: &[(1,5),(1,5),(1,5),(1,5),(1,5),(2,4),(3,5)], 13 + ans_expression: | v: &[f32] | -> f32 { 14 + v[0]*(v[5].powf(&v[0]-1.0)) + v[1]*v[5].powf(&v[1]-1.0)*v[6].powf(v[6]) - v[3]*v[6].powf(v[4]) 15 + }} 16 + } 17 + 18 + // f_y( {} , {} ) = ? 19 + // giving answer gets complicated with closures for now lets keep a single answer 20 + // x => 5, y=>6
+17 -57
src/util.rs
··· 1 - 2 - use std::str::FromStr; 3 1 4 2 use axum::{http::{HeaderMap, header}, response::IntoResponse}; 3 + use dyn_fmt::AsStrFormatExt; 5 4 use genpdf::{Document, elements::{self, Paragraph}, style}; 6 5 use rand::random_range; 7 6 use crate::GenpdfState; ··· 36 35 37 36 } 38 37 39 - #[derive(Debug,PartialEq)] 40 - pub struct Question { 38 + pub struct Question<F> 39 + where F: Fn(&[f32])-> f32 40 + { 41 41 pub subject: Subject, 42 42 pub theme: Theme, 43 - pub text: String, 44 - pub var_conditions: Vec<(i32,i32)>, 45 - pub ans_expression: Option<String> 43 + pub text: &'static str, 44 + pub var_conditions: &'static [(i32,i32)], 45 + pub ans_expression: F 46 46 } 47 47 48 48 #[derive(Debug,Display)] ··· 51 51 Strum(strum::ParseError) 52 52 } 53 53 54 - impl FromStr for Question { 55 - type Err = QuestionParseError; 56 - fn from_str(s: &str) -> Result<Self, Self::Err> { 57 - let l : Vec<&str> = s.splitn(5, ";\n").collect(); 58 - let subj: Subject = Subject::from_str(l[0]).unwrap(); 59 - let theme: Theme = match subj { 60 - Subject::Math => Theme::Math( match MathTheme::from_str(l[1]) { 61 - Ok(t) => t, 62 - Err(err) => panic!("{err}: string {0}",l[1]) 63 - }), 64 - Subject::Physics => Theme::Physics(PhysTheme::from_str(l[1]).unwrap()), 65 - }; 66 - if l[2].is_empty() { 67 - return Err(QuestionParseError::QuestionFileParseError); 68 - } 69 - let var_amount = l[2].to_string().matches("{{").collect::<Vec<_>>().len(); 70 - if l[3].is_empty() { 71 - return Err(QuestionParseError::QuestionFileParseError); 72 - } 73 - let lines = l[3].lines().collect::<Vec<_>>(); 74 - if !(lines.len() == var_amount) { 75 - return Err(QuestionParseError::QuestionFileParseError); 76 - } 77 54 78 - let var_conf:Vec<(i32,i32)> = lines.iter().map(|x| { 79 - let elements:Vec<_> = x.split(",").collect(); 80 - (elements[0].parse().unwrap(),elements[1].parse().unwrap()) 81 - } 82 - ).collect(); 55 + impl<F> Question<F> 56 + where F: Fn(&[f32])-> f32 57 + { 58 + pub fn generate_question(&self) -> (String,String) { 59 + let vars:Vec<i32> = self.var_conditions.iter().map(|x| { 60 + random_range(x.0..x.1) 61 + }).collect(); 62 + let text = self.text.format(&vars[..]); 83 63 84 - if l.len() < 4 { 85 - Ok(Question { subject: subj, theme: theme, text: l[2].to_string(),var_conditions:var_conf ,ans_expression: Some(l[4].to_string()) }) 86 - } else { 87 - Ok(Question { subject: subj, theme: theme, text: l[2].to_string(),var_conditions:var_conf ,ans_expression: None }) 88 - } 89 - } 64 + let answer = (self.ans_expression)(vars.iter().map(|x| *x as f32).collect::<Vec<f32>>().iter().as_slice()); 90 65 91 - } 92 - 93 - 94 - impl Question { 95 - pub fn generate_question(&self) -> String { 96 - let text = self.text.split_whitespace().map(|x| { 97 - if x.contains("{{") { 98 - if x[0..2] == *"{{" && x[3..5] == *"}}" { 99 - let var_num:usize = x.chars().nth(2).unwrap().to_string().parse().unwrap(); 100 - return format!("{}",random_range(self.var_conditions[var_num].0..self.var_conditions[var_num].1)).to_string(); 101 - } 102 - } 103 - x.to_string() 104 - }).collect(); 105 - 106 - text 66 + (text.to_string(),format!("{}",answer)) 107 67 } 108 68 109 69 }