forked from asklyphe-public/asklyphe
		
	Compare commits
	
		
			20 commits
		
	
	
		
			f11aa99038
			...
			5b1e215b77
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5b1e215b77 | |||
| b101b5af51 | |||
| 86c6c96909 | |||
| cd493f8d32 | |||
| 74b29455e5 | |||
| 47477732ba | |||
| cbf35e9746 | |||
| adf97d4b20 | |||
| 328ec0bfdc | |||
| 199bce4f90 | |||
| 9c9172d4c9 | |||
| 4f6063bf72 | |||
| b7b466b774 | |||
| 25644b9d4e | |||
| 849393fbd1 | |||
| c2f210c32c | |||
| 7a57c7bf1e | |||
| fe539a637e | |||
| 0725850ad0 | |||
| de1d9931b1 | 
					 9 changed files with 578 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -265,6 +265,7 @@ dependencies = [
 | 
				
			||||||
 "askama",
 | 
					 "askama",
 | 
				
			||||||
 "askama_axum",
 | 
					 "askama_axum",
 | 
				
			||||||
 "asklyphe-common",
 | 
					 "asklyphe-common",
 | 
				
			||||||
 | 
					 "astro-float",
 | 
				
			||||||
 "async-nats",
 | 
					 "async-nats",
 | 
				
			||||||
 "axum",
 | 
					 "axum",
 | 
				
			||||||
 "axum-extra",
 | 
					 "axum-extra",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,4 +39,6 @@ url_encoded_data = "0.6.1"
 | 
				
			||||||
strum = "0.27.1"
 | 
					strum = "0.27.1"
 | 
				
			||||||
strum_macros = "0.27.1"
 | 
					strum_macros = "0.27.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					astro-float = "0.9.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
env_logger = "*"
 | 
					env_logger = "*"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ pub mod searchbot;
 | 
				
			||||||
pub mod wikipedia;
 | 
					pub mod wikipedia;
 | 
				
			||||||
pub mod unit_converter;
 | 
					pub mod unit_converter;
 | 
				
			||||||
pub mod bangs;
 | 
					pub mod bangs;
 | 
				
			||||||
 | 
					pub mod math;
 | 
				
			||||||
pub mod routes;
 | 
					pub mod routes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::{env, process};
 | 
					use std::{env, process};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										448
									
								
								asklyphe-frontend/src/math.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										448
									
								
								asklyphe-frontend/src/math.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,448 @@
 | 
				
			||||||
 | 
					use tracing::{debug, error};
 | 
				
			||||||
 | 
					use once_cell::sync::Lazy;
 | 
				
			||||||
 | 
					use astro_float::{BigFloat, Sign, RoundingMode, Consts};
 | 
				
			||||||
 | 
					use std::str::FromStr;
 | 
				
			||||||
 | 
					use std::sync::{Arc, Mutex};
 | 
				
			||||||
 | 
					use std::mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const PRECISION: usize = 2048;
 | 
				
			||||||
 | 
					static CONST_CACHE: Lazy<Arc<Mutex<Consts>>> = Lazy::new(|| Arc::new(Mutex::new(Consts::new().expect("Unable to allocate memory for Conts cache"))));
 | 
				
			||||||
 | 
					// static PI: Lazy<BigFloat> = Lazy::new(|| BigFloat::from_str("3.141592653589793238462643383279").unwrap());
 | 
				
			||||||
 | 
					// static E: Lazy<BigFloat> = Lazy::new(|| BigFloat::from_str("2.718281828459045235360287471352").unwrap());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct Calculation {
 | 
				
			||||||
 | 
						pub equation: String,
 | 
				
			||||||
 | 
						pub result: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn calculate(query: &str) -> Option<Calculation> {
 | 
				
			||||||
 | 
						debug!("Got query {}", query);
 | 
				
			||||||
 | 
						let mut parser = Parser::new(Lexer::new(query));
 | 
				
			||||||
 | 
						let mut tree = parser.parse()?;
 | 
				
			||||||
 | 
						let res = tree.eval();
 | 
				
			||||||
 | 
						let res_float = f64::from_str(&format!("{}", res)).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						debug!("Calculation: {}", query);
 | 
				
			||||||
 | 
						debug!("Tree: {:?}", tree);
 | 
				
			||||||
 | 
						debug!("Result: {:?}", res_float);
 | 
				
			||||||
 | 
						Some(Calculation {equation: query.to_string(), result: res_float.to_string()})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: put into own crate with dependency astro-float = "0.9.2" so I can use more than BigFloat
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
 | 
					enum Token {
 | 
				
			||||||
 | 
						Op(Op),
 | 
				
			||||||
 | 
						Atom(Atom),
 | 
				
			||||||
 | 
					/*	Number(BigFloat),
 | 
				
			||||||
 | 
						Func(Func),*/
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
 | 
					enum Op {
 | 
				
			||||||
 | 
						Add,
 | 
				
			||||||
 | 
						Subtract,
 | 
				
			||||||
 | 
						Multiply,
 | 
				
			||||||
 | 
						Divide,
 | 
				
			||||||
 | 
						Exponent,
 | 
				
			||||||
 | 
						LParen,
 | 
				
			||||||
 | 
						RParen,
 | 
				
			||||||
 | 
						Func(Func), // A function is an Op that takes whatever the next thing is and binds it, either the next number or whatever is in parens
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Op {
 | 
				
			||||||
 | 
						fn bp_infix(&self) -> Option<(f64, f64)> {
 | 
				
			||||||
 | 
							match self {
 | 
				
			||||||
 | 
								// Op::LParen => Some(0.0),
 | 
				
			||||||
 | 
								// Op::RParen => Some(0.0),
 | 
				
			||||||
 | 
								Op::Add => Some((1.0, 1.1)),
 | 
				
			||||||
 | 
								Op::Subtract => Some((1.0, 1.1)),
 | 
				
			||||||
 | 
								Op::Multiply => Some((2.0, 2.1)),
 | 
				
			||||||
 | 
								Op::Divide => Some((2.0, 2.1)),
 | 
				
			||||||
 | 
								Op::Exponent => Some((3.1, 3.0)),
 | 
				
			||||||
 | 
								_ => None,
 | 
				
			||||||
 | 
								// Op::Func(_) => 0.0, // TODO: decide if this is a good LBP
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn bp_prefix(&self) -> Option<f64> {
 | 
				
			||||||
 | 
							match self {
 | 
				
			||||||
 | 
								Op::Func(_) => Some(6.0),
 | 
				
			||||||
 | 
								Op::Subtract => Some(5.0),
 | 
				
			||||||
 | 
								Op::Add => Some(5.0),
 | 
				
			||||||
 | 
								_ => None,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn apply_to(&self, args: &mut Vec<Expr>) -> BigFloat {
 | 
				
			||||||
 | 
							match args.len() {
 | 
				
			||||||
 | 
								1 => match self {
 | 
				
			||||||
 | 
									Op::Subtract => {
 | 
				
			||||||
 | 
										let mut res = args[0].eval();
 | 
				
			||||||
 | 
										res.set_sign(Sign::Neg);
 | 
				
			||||||
 | 
										res
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Op::Add => {
 | 
				
			||||||
 | 
										let mut res = args[0].eval();
 | 
				
			||||||
 | 
										res.set_sign(Sign::Pos);
 | 
				
			||||||
 | 
										res
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									Op::Func(f) => match f {
 | 
				
			||||||
 | 
										Func::Sine => args[0].eval().sin(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::Cosine => args[0].eval().cos(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::Tangent => args[0].eval().tan(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::ArcSine => args[0].eval().asin(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::ArcCosine => args[0].eval().acos(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::ArcTangent => args[0].eval().atan(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::Log2 => args[0].eval().log2(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::Log10 => args[0].eval().log10(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::LogN => args[0].eval().ln(PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::Square => args[0].eval().pow(&BigFloat::from_f64(2.0, PRECISION), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
										Func::SquareRoot => args[0].eval().sqrt(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
										Func::Abs => args[0].eval().abs(),
 | 
				
			||||||
 | 
										_ => {
 | 
				
			||||||
 | 
											error!("Got 1 params for func {:?} which expects 2 (should not be possible)", self);
 | 
				
			||||||
 | 
											astro_float::NAN
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									_ => {
 | 
				
			||||||
 | 
										error!("Got 1 params for {:?} which expects 2 (should not be possible)", self);
 | 
				
			||||||
 | 
										astro_float::NAN
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								2 => match self {
 | 
				
			||||||
 | 
									Op::LParen => args[0].eval(),
 | 
				
			||||||
 | 
									Op::RParen => args[0].eval(),
 | 
				
			||||||
 | 
									Op::Add => args[0].eval().add(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
									Op::Subtract => args[0].eval().sub(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
									Op::Multiply => args[0].eval().mul(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
									Op::Divide => args[0].eval().div(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
									Op::Exponent => args[0].eval().pow(&mut args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
									Op::Func(Func::Log) => args[0].eval().log(&mut args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
 | 
									_ => {
 | 
				
			||||||
 | 
										error!("Got 2 params for {:?} which only expects 1 (should not be possible)", self);
 | 
				
			||||||
 | 
										astro_float::NAN
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_ => {
 | 
				
			||||||
 | 
									error!("Unexpected number of params ({}) for {:?} (should not be possible)", args.len(), self);
 | 
				
			||||||
 | 
									astro_float::NAN
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
 | 
					enum Atom {
 | 
				
			||||||
 | 
						Number(BigFloat),
 | 
				
			||||||
 | 
						Const(Const),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*impl Atom {
 | 
				
			||||||
 | 
						fn get_val(&self) -> BigFloat {
 | 
				
			||||||
 | 
							match self {
 | 
				
			||||||
 | 
								Atom::Number(val) => *val,
 | 
				
			||||||
 | 
								Atom::Const(c) => match c {
 | 
				
			||||||
 | 
									Const::Pi => CONST_CACHE.lock().unwrap().pi(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
									Const::E => CONST_CACHE.lock().unwrap().e(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
									Const::Inf => astro_float::INF_POS,
 | 
				
			||||||
 | 
									Const::Nan => astro_float::NAN,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Const {
 | 
				
			||||||
 | 
						fn get_val(&self) -> BigFloat {
 | 
				
			||||||
 | 
							match self {
 | 
				
			||||||
 | 
								Const::Pi => CONST_CACHE.lock().unwrap().pi(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
								Const::E => CONST_CACHE.lock().unwrap().e(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
								Const::Inf => astro_float::INF_POS,
 | 
				
			||||||
 | 
								Const::Nan => astro_float::NAN,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
 | 
					enum Func {
 | 
				
			||||||
 | 
						Sine,
 | 
				
			||||||
 | 
						Cosine,
 | 
				
			||||||
 | 
						Tangent,
 | 
				
			||||||
 | 
						// sin-1, cos-1, tan-1
 | 
				
			||||||
 | 
						ArcSine,
 | 
				
			||||||
 | 
						ArcCosine,
 | 
				
			||||||
 | 
						ArcTangent,
 | 
				
			||||||
 | 
						Log2,
 | 
				
			||||||
 | 
						Log10,
 | 
				
			||||||
 | 
						LogN,
 | 
				
			||||||
 | 
						Log,
 | 
				
			||||||
 | 
						Square,
 | 
				
			||||||
 | 
						SquareRoot,
 | 
				
			||||||
 | 
						Abs,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Func {
 | 
				
			||||||
 | 
						fn names() -> &'static [(Func, &'static [&'static str])] {
 | 
				
			||||||
 | 
							&[
 | 
				
			||||||
 | 
								(Func::Sine, &["sin", "sine"]),
 | 
				
			||||||
 | 
								(Func::Cosine, &["cos", "cosine"]),
 | 
				
			||||||
 | 
								(Func::Tangent, &["tan", "tangent"]),
 | 
				
			||||||
 | 
								(Func::ArcSine, &["asin", "asine", "arcsin", "arcsine"]),
 | 
				
			||||||
 | 
								(Func::ArcCosine, &["acos", "acosine", "arccos", "arccosine"]),
 | 
				
			||||||
 | 
								(Func::ArcTangent, &["atan", "atangent", "arctan", "arctangent"]),
 | 
				
			||||||
 | 
								(Func::Log2, &["log2"]),
 | 
				
			||||||
 | 
								(Func::Log10, &["log10"]),
 | 
				
			||||||
 | 
								(Func::LogN, &["ln", "logn"]),
 | 
				
			||||||
 | 
								(Func::Log, &["log"]),
 | 
				
			||||||
 | 
								(Func::Square, &["square", "squared"]),
 | 
				
			||||||
 | 
								(Func::SquareRoot, &["sqrt", "squareroot", "√"]),
 | 
				
			||||||
 | 
								(Func::Abs, &["abs", "absolute"]),
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
 | 
					enum Const {
 | 
				
			||||||
 | 
						Pi,
 | 
				
			||||||
 | 
						E,
 | 
				
			||||||
 | 
						Inf,
 | 
				
			||||||
 | 
						Nan,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Const {
 | 
				
			||||||
 | 
						fn names() -> &'static [(Const, &'static [&'static str])] {
 | 
				
			||||||
 | 
							&[
 | 
				
			||||||
 | 
								(Const::Pi, &["pi", "PI", "π"]),
 | 
				
			||||||
 | 
								(Const::E, &["e", "euler"]),
 | 
				
			||||||
 | 
								(Const::Inf, &["inf", "infinity", "∞"]),
 | 
				
			||||||
 | 
								(Const::Nan, &["nan", "NaN"])
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
 | 
					enum ParseErr {
 | 
				
			||||||
 | 
						Eof,
 | 
				
			||||||
 | 
						Invalid,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// this can probably be swapped out with a lexer generator like Logos if needed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Lexer<'a> {
 | 
				
			||||||
 | 
						data: &'a str,
 | 
				
			||||||
 | 
						data_ptr: &'a str,
 | 
				
			||||||
 | 
						// idx: usize,
 | 
				
			||||||
 | 
						next_by: usize,
 | 
				
			||||||
 | 
						next_tok: Result<Token, ParseErr>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: refactor with iterator that returns Option(Token) where one token option is Eof (or a enum of Token(Token) and Eof, or just Option(Option(Token)))
 | 
				
			||||||
 | 
					impl Lexer<'_> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn new(data: &str) -> Lexer<'_> {
 | 
				
			||||||
 | 
							let mut n: Lexer = Lexer {data, data_ptr: data, next_by: 0, next_tok: Err(ParseErr::Eof)};
 | 
				
			||||||
 | 
							n.next();
 | 
				
			||||||
 | 
							debug!("New finished!");
 | 
				
			||||||
 | 
							n
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						fn _next(&mut self) -> Result<Token, ParseErr> {
 | 
				
			||||||
 | 
							self.data_ptr = &self.data_ptr[self.next_by..];
 | 
				
			||||||
 | 
							match self.data_ptr.chars().nth(0) {
 | 
				
			||||||
 | 
								Some(val) => {
 | 
				
			||||||
 | 
									debug!("lexing char '{}' at idx {}", val, self.data.chars().count() - self.data_ptr.chars().count());
 | 
				
			||||||
 | 
									self.next_by = 1;
 | 
				
			||||||
 | 
									match val {
 | 
				
			||||||
 | 
										'+' => Ok(Token::Op(Op::Add)),
 | 
				
			||||||
 | 
										'-' => Ok(Token::Op(Op::Subtract)),
 | 
				
			||||||
 | 
										'×' | '*' => Ok(Token::Op(Op::Multiply)),
 | 
				
			||||||
 | 
										'÷' | '/' => Ok(Token::Op(Op::Divide)),
 | 
				
			||||||
 | 
										'^' => Ok(Token::Op(Op::Exponent)),
 | 
				
			||||||
 | 
										'(' => Ok(Token::Op(Op::LParen)),
 | 
				
			||||||
 | 
										')' => Ok(Token::Op(Op::RParen)),
 | 
				
			||||||
 | 
										_ if val.is_whitespace() => self._next(),
 | 
				
			||||||
 | 
										_ if val.is_digit(10) => {
 | 
				
			||||||
 | 
											let mut len: usize = 0;
 | 
				
			||||||
 | 
											self.data_ptr.chars().take_while(|c| c.is_digit(10) || *c == '.').for_each(|_| len += 1);
 | 
				
			||||||
 | 
											self.next_by = len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											match self.data_ptr[..len].parse() {
 | 
				
			||||||
 | 
												Ok(val) => Ok(Token::Atom(Atom::Number(val))),
 | 
				
			||||||
 | 
												Err(e) => Err(ParseErr::Invalid),
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										_ => {
 | 
				
			||||||
 | 
											let len = self.data_ptr.chars().count();
 | 
				
			||||||
 | 
											for (f, names) in Func::names() {
 | 
				
			||||||
 | 
												for name in *names {
 | 
				
			||||||
 | 
													let n_len = name.chars().count();
 | 
				
			||||||
 | 
													if self.data_ptr.starts_with(name) && (len == n_len || !self.data_ptr.chars().nth(n_len).unwrap().is_alphabetic()) {
 | 
				
			||||||
 | 
														self.next_by = name.chars().count();
 | 
				
			||||||
 | 
														return Ok(Token::Op(Op::Func(*f)));
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											for (f, names) in Const::names() {
 | 
				
			||||||
 | 
												for name in *names {
 | 
				
			||||||
 | 
													let n_len = name.chars().count();
 | 
				
			||||||
 | 
													if self.data_ptr.starts_with(name) && (len == n_len || !self.data_ptr.chars().nth(n_len).unwrap().is_alphabetic()) {
 | 
				
			||||||
 | 
														self.next_by = name.chars().count();
 | 
				
			||||||
 | 
														return Ok(Token::Atom(Atom::Const(*f)));
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											debug!("got invalid char '{}'", val);
 | 
				
			||||||
 | 
											Err(ParseErr::Invalid)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								None => {
 | 
				
			||||||
 | 
									self.next_by = 0;
 | 
				
			||||||
 | 
									Err(ParseErr::Eof)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn next(&mut self) -> Result<Token, ParseErr> {
 | 
				
			||||||
 | 
							let res = self._next();
 | 
				
			||||||
 | 
							let val = mem::replace(&mut self.next_tok, res);
 | 
				
			||||||
 | 
							// self.next_tok = self._next();
 | 
				
			||||||
 | 
							val
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn peek(&mut self) -> &Result<Token, ParseErr> {
 | 
				
			||||||
 | 
							&self.next_tok
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: replace with iterator so I can do parser.parse(lexer.iter()) and parse does lex_iter.next() & such
 | 
				
			||||||
 | 
						fn lex_all(&mut self) -> Option<Vec<Token>> {
 | 
				
			||||||
 | 
							let mut tokens: Vec<Token> = vec![];
 | 
				
			||||||
 | 
							loop {
 | 
				
			||||||
 | 
								match self.next() {
 | 
				
			||||||
 | 
									Err(ParseErr::Eof) => return Some(tokens),
 | 
				
			||||||
 | 
									Err(ParseErr::Invalid) => return None,
 | 
				
			||||||
 | 
									Ok(tok) => tokens.push(tok),
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// debug!("tokens: {:?}", tokens);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn matches(s: &str, check: &str) -> usize {
 | 
				
			||||||
 | 
						// debug!("s: \"{}\", check: \"{}\"c_len: {}, s_len: {}, s[c_len]: {:?}, s[c_len + 1]: {:?}", s, check, check.chars().count(), s.chars().count(), s.chars().nth(check.chars().count()), s.chars().nth(check.chars().count() + 1));
 | 
				
			||||||
 | 
						match (s.chars().count(), check.chars().count()) {
 | 
				
			||||||
 | 
							(s_len, c_len) if s_len < c_len => 0,
 | 
				
			||||||
 | 
							(s_len, c_len) if s_len == c_len && s == check => c_len - 1,
 | 
				
			||||||
 | 
							(s_len, c_len) if s_len > c_len && s.starts_with(check) && s.chars().nth(c_len).unwrap().is_whitespace() => c_len,
 | 
				
			||||||
 | 
							(_, _) => 0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Parser<'a> {
 | 
				
			||||||
 | 
						lex: Lexer<'a>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Parser<'_> {
 | 
				
			||||||
 | 
						fn new(lex: Lexer) -> Parser { Parser {lex} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn parse(&mut self) -> Option<Expr> {
 | 
				
			||||||
 | 
							self.parse_expr(0.0).ok()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn parse_expr(&mut self, min_bp: f64) -> Result<Expr, ParseErr> {
 | 
				
			||||||
 | 
							/*while let Ok(val) = self.lex.next() {debug!("token: {:?}", val)}
 | 
				
			||||||
 | 
							match self.lex.next().err() {
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								_ => return Err(ParseErr::Invalid),
 | 
				
			||||||
 | 
							}*/
 | 
				
			||||||
 | 
							let mut lhs: Expr = match self.lex.next() {
 | 
				
			||||||
 | 
								Ok(val) => match val {
 | 
				
			||||||
 | 
									Token::Atom(val) => Ok(Expr::Atom(val)),
 | 
				
			||||||
 | 
									Token::Op(op) => match op {
 | 
				
			||||||
 | 
										Op::LParen => {
 | 
				
			||||||
 | 
											let val = self.parse_expr(0.0);
 | 
				
			||||||
 | 
											if self.lex.next() != Ok(Token::Op(Op::RParen)) {
 | 
				
			||||||
 | 
												debug!("Unclosed parens");
 | 
				
			||||||
 | 
												Err(ParseErr::Invalid)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											else {
 | 
				
			||||||
 | 
												val
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										// Op::Func(f) => Ok(Expr::Node(Op::Func(f), vec![self.parse_expr(op.get_lbp())?])),
 | 
				
			||||||
 | 
										_ => match op.bp_prefix() {
 | 
				
			||||||
 | 
											Some(bp) => Ok(Expr::Node(op, vec![self.parse_expr(bp)?])),
 | 
				
			||||||
 | 
											None => {debug!("Got unexpected {:?} as prefix", op); Err(ParseErr::Invalid)}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Err(err) => Err(err),
 | 
				
			||||||
 | 
							}.map_err(|err| { debug!("Unexpected error at start of expr: {:?}", err); err })?;
 | 
				
			||||||
 | 
							debug!("lhs of expression is {:?}, min_bp is {}", lhs, min_bp);
 | 
				
			||||||
 | 
							loop {
 | 
				
			||||||
 | 
								debug!("loop start");
 | 
				
			||||||
 | 
								let op: Op = match self.lex.peek() {
 | 
				
			||||||
 | 
									Err(ParseErr::Eof) => break,
 | 
				
			||||||
 | 
									Err(e) => { debug!("In expr got err {:?}", e); Err(*e) },
 | 
				
			||||||
 | 
									Ok(tok) => match tok {
 | 
				
			||||||
 | 
										Token::Op(op) => match op {
 | 
				
			||||||
 | 
											Op::RParen => {
 | 
				
			||||||
 | 
												debug!("got RParen");
 | 
				
			||||||
 | 
												break;
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											_ => Ok(*op),
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}.map_err(|err| { debug!("Unexpected error inside expr at {:?}", err); err })?;
 | 
				
			||||||
 | 
								debug!("op is {:?}", op);
 | 
				
			||||||
 | 
								if let Some((lbp, rbp)) = op.bp_infix() {
 | 
				
			||||||
 | 
									if (lbp < min_bp) { break; }
 | 
				
			||||||
 | 
									self.lex.next();
 | 
				
			||||||
 | 
									let rhs: Expr = self.parse_expr(rbp)?;
 | 
				
			||||||
 | 
									lhs = Expr::Node(op, vec![lhs, rhs]);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									debug!("Got unexpected non-infix operator in expression: {:?}", op);
 | 
				
			||||||
 | 
									return Err(ParseErr::Invalid);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							debug!("Returning expr {:?}", lhs);
 | 
				
			||||||
 | 
							Ok(lhs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					enum Expr {
 | 
				
			||||||
 | 
						Evaluated,
 | 
				
			||||||
 | 
						Atom(Atom),
 | 
				
			||||||
 | 
						Node(Op, Vec<Expr>),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Expr {
 | 
				
			||||||
 | 
						fn eval(&mut self) -> BigFloat {
 | 
				
			||||||
 | 
							let res = match self {
 | 
				
			||||||
 | 
								Expr::Atom(_) => {
 | 
				
			||||||
 | 
									let v = mem::replace(self, Expr::Evaluated);
 | 
				
			||||||
 | 
									if let Expr::Atom(at) = v {
 | 
				
			||||||
 | 
										match at {
 | 
				
			||||||
 | 
											Atom::Number(n) => n,
 | 
				
			||||||
 | 
											Atom::Const(c) => c.get_val(),
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										unreachable!();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// at.get_val()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Expr::Node(op, exprs) => {
 | 
				
			||||||
 | 
									*self = Expr::Atom(Atom::Number(op.apply_to(exprs)));
 | 
				
			||||||
 | 
									self.eval()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Expr::Evaluated => unreachable!("Tried to evaluate an already evaluated node"),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							// debug!("{:?} evaluated to {}", self, res);
 | 
				
			||||||
 | 
							res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,8 @@ use crate::unit_converter::UnitConversion;
 | 
				
			||||||
use crate::wikipedia::WikipediaSummary;
 | 
					use crate::wikipedia::WikipediaSummary;
 | 
				
			||||||
use crate::{wikipedia, Opts, ALPHA, BUILT_ON, GIT_COMMIT, VERSION, YEAR};
 | 
					use crate::{wikipedia, Opts, ALPHA, BUILT_ON, GIT_COMMIT, VERSION, YEAR};
 | 
				
			||||||
use crate::bangs;
 | 
					use crate::bangs;
 | 
				
			||||||
 | 
					use crate::math;
 | 
				
			||||||
 | 
					use crate::math::Calculation;
 | 
				
			||||||
use askama::Template;
 | 
					use askama::Template;
 | 
				
			||||||
use asklyphe_common::nats;
 | 
					use asklyphe_common::nats;
 | 
				
			||||||
use asklyphe_common::nats::bingservice::{
 | 
					use asklyphe_common::nats::bingservice::{
 | 
				
			||||||
| 
						 | 
					@ -69,6 +71,7 @@ pub struct Complications {
 | 
				
			||||||
    disabled: bool,
 | 
					    disabled: bool,
 | 
				
			||||||
    wikipedia: Option<WikipediaSummary>,
 | 
					    wikipedia: Option<WikipediaSummary>,
 | 
				
			||||||
    unit_converter: Option<UnitConversion>,
 | 
					    unit_converter: Option<UnitConversion>,
 | 
				
			||||||
 | 
					    math: Option<Calculation>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn search(
 | 
					pub async fn search(
 | 
				
			||||||
| 
						 | 
					@ -176,6 +179,11 @@ pub async fn search_js(
 | 
				
			||||||
            if let Some(redirect) = bang_redirect {
 | 
					            if let Some(redirect) = bang_redirect {
 | 
				
			||||||
                return Redirect::to(&redirect).into_response();
 | 
					                return Redirect::to(&redirect).into_response();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let mut calc_query = query.clone().to_lowercase();
 | 
				
			||||||
 | 
					            calc_query = calc_query.replace("calculate", "").replace("what is", "");
 | 
				
			||||||
 | 
					            let math = math::calculate(&calc_query);
 | 
				
			||||||
 | 
					            complications.math = math;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            complications.disabled = true;
 | 
					            complications.disabled = true;
 | 
				
			||||||
            query = query.replace("-complications", "");
 | 
					            query = query.replace("-complications", "");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,6 +67,13 @@
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        {% when None %}
 | 
					                        {% when None %}
 | 
				
			||||||
                        {% endmatch %}
 | 
					                        {% endmatch %}
 | 
				
			||||||
 | 
					                        {% match complications.math %}
 | 
				
			||||||
 | 
					                        {% when Some with (math) %}
 | 
				
			||||||
 | 
					                        <div class="calculator-complication">
 | 
				
			||||||
 | 
					                            <h1>{{ math.equation }} = {{ math.result }}</h1>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                        {% when None %}
 | 
				
			||||||
 | 
					                        {% endmatch %}
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                {% endmatch %}
 | 
					                {% endmatch %}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								cert.pem
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								cert.pem
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIF7zCCA9egAwIBAgIUb46GxLSqbrjV/nlD+ovwlYcyzOcwDQYJKoZIhvcNAQEL
 | 
				
			||||||
 | 
					BQAwgYYxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcM
 | 
				
			||||||
 | 
					CENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFu
 | 
				
			||||||
 | 
					eVNlY3Rpb25OYW1lMR0wGwYDVQQDDBRDb21tb25OYW1lT3JIb3N0bmFtZTAeFw0y
 | 
				
			||||||
 | 
					NTA2MjEwNTA1NTlaFw0zNTA2MTkwNTA1NTlaMIGGMQswCQYDVQQGEwJYWDESMBAG
 | 
				
			||||||
 | 
					A1UECAwJU3RhdGVOYW1lMREwDwYDVQQHDAhDaXR5TmFtZTEUMBIGA1UECgwLQ29t
 | 
				
			||||||
 | 
					cGFueU5hbWUxGzAZBgNVBAsMEkNvbXBhbnlTZWN0aW9uTmFtZTEdMBsGA1UEAwwU
 | 
				
			||||||
 | 
					Q29tbW9uTmFtZU9ySG9zdG5hbWUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
 | 
				
			||||||
 | 
					AoICAQC28URbBWcTpvOar679u4CwsAHQ+i+9iPBvjRG/ShdvXkAgWm+t/BvKi9JG
 | 
				
			||||||
 | 
					FOAn49IKOpcteY15qvDFRPDKk8YWoiwdMQSKRNEwEow3YlIs6xX94+PNdwsjaqy/
 | 
				
			||||||
 | 
					mhJTMh0xrElZJ5+B4mDXQHOzdS6fe0SlNhqEAkFaIuUNX1NAks7yRnkC5LGkSHHj
 | 
				
			||||||
 | 
					gD2ZThwyZ+cstvT7WEUN9uMz/FfLuQQLrVZDydE9tsoQo0CIl1l0NLiE0BN5RIwi
 | 
				
			||||||
 | 
					i6Gkao74jlxh6tXv7XcOTxZ1aV3F92qMKN1NtWFEqpC2PDdfLG5iAlwamKguD24N
 | 
				
			||||||
 | 
					RMDC9CGCiutE4lRhRQWkC89NSxOkG25MGRvK0jut7MiKOia/Xk5uJI2Rid9IWFKv
 | 
				
			||||||
 | 
					xnuT5AW9PCbjM0OSkw2G0PzthUAO1jrOyA2R50oh/YGsdslELhlpZSiu/StSx+0U
 | 
				
			||||||
 | 
					x0E9dcQHvnlllU5BrYXbDkoSCiejhD4xV35KmhIwtz7pr2cajfeJ5r7Em/hSBVbS
 | 
				
			||||||
 | 
					Zqbv5OmGgxTSSDLUTaLJA015vLnLNCV5al/iGzXKl1FOwTIzRLv+og/jK70rwOGX
 | 
				
			||||||
 | 
					Red2JnKntqfBEnR51gky9axyyz3dAMEE1rCc+oOv7ycZoEKwPdXiyneOCLT40QT6
 | 
				
			||||||
 | 
					No1UrMJCa32a4+YJgbANB8igFwwhdapD5N+qvpCWtiKsdnbPeQIDAQABo1MwUTAd
 | 
				
			||||||
 | 
					BgNVHQ4EFgQUq3zHWtMlNawKBIPiOECsuPWTB7IwHwYDVR0jBBgwFoAUq3zHWtMl
 | 
				
			||||||
 | 
					NawKBIPiOECsuPWTB7IwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
 | 
				
			||||||
 | 
					AgEAtoERmowTDvnZFV4ETGmj3mPXNLXaqSUDRAB5ol9N4NlRU/vFjI70sYV7uco9
 | 
				
			||||||
 | 
					628Wc5SLbA66wSmpnq5t1MeTjjra6o6bj5wOKixo1gmpUq7Ru1JmVWsNIo/Zv4ew
 | 
				
			||||||
 | 
					rmCxuapHL0U9R0P1qpJe0tYzSMFikgkFmHyL86HcuW8B/Ps3bGaGlamqmIK3HlP4
 | 
				
			||||||
 | 
					Ib+sOtInNZ1Td8eYTIYO5Nk5ko/4rjZrv9+3aZdjde1z/M2VduGGH8TCExD55Rbv
 | 
				
			||||||
 | 
					+UL8fGIEkfSNTeiA5SAN3dfqcra703mfOJfjJeoubfk8KowfGb/bVKv8Z8rkEDOj
 | 
				
			||||||
 | 
					so+sOgbq1xnSaQov7WRqYZ0yKZA0u8Arc0L8CX/rwgwoBkQafySEI/32Mqt0R4/w
 | 
				
			||||||
 | 
					MkmGZLSFTcIFrQVE+wBHTilQ1PfUmAA6kh7ks7SGwlc6KxTAtYZHWklCqib0efaJ
 | 
				
			||||||
 | 
					AbODBc97vLrR5qoH0VFSGLnjDVEYHb6TREqsCZR+9EP/JcsTRJ8RTeDVg8RnN2a6
 | 
				
			||||||
 | 
					uy01L7A3d1xnXPux45fpwgGTOEig2sD0BTHZW/bl53xQr8gJvwyr78cIVmycT/6N
 | 
				
			||||||
 | 
					K0AmYBPQWZLf6rxtommjMgf2DtvhPm6VrbHV7epk8cw8tOVRPD5uLjZzKxgFoZez
 | 
				
			||||||
 | 
					ZYNjSUse3ChC7l4FhjmTiI5DWOrS/qYbWYi9rzvG6QZwHss=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										52
									
								
								key.pem
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								key.pem
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,52 @@
 | 
				
			||||||
 | 
					-----BEGIN PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC28URbBWcTpvOa
 | 
				
			||||||
 | 
					r679u4CwsAHQ+i+9iPBvjRG/ShdvXkAgWm+t/BvKi9JGFOAn49IKOpcteY15qvDF
 | 
				
			||||||
 | 
					RPDKk8YWoiwdMQSKRNEwEow3YlIs6xX94+PNdwsjaqy/mhJTMh0xrElZJ5+B4mDX
 | 
				
			||||||
 | 
					QHOzdS6fe0SlNhqEAkFaIuUNX1NAks7yRnkC5LGkSHHjgD2ZThwyZ+cstvT7WEUN
 | 
				
			||||||
 | 
					9uMz/FfLuQQLrVZDydE9tsoQo0CIl1l0NLiE0BN5RIwii6Gkao74jlxh6tXv7XcO
 | 
				
			||||||
 | 
					TxZ1aV3F92qMKN1NtWFEqpC2PDdfLG5iAlwamKguD24NRMDC9CGCiutE4lRhRQWk
 | 
				
			||||||
 | 
					C89NSxOkG25MGRvK0jut7MiKOia/Xk5uJI2Rid9IWFKvxnuT5AW9PCbjM0OSkw2G
 | 
				
			||||||
 | 
					0PzthUAO1jrOyA2R50oh/YGsdslELhlpZSiu/StSx+0Ux0E9dcQHvnlllU5BrYXb
 | 
				
			||||||
 | 
					DkoSCiejhD4xV35KmhIwtz7pr2cajfeJ5r7Em/hSBVbSZqbv5OmGgxTSSDLUTaLJ
 | 
				
			||||||
 | 
					A015vLnLNCV5al/iGzXKl1FOwTIzRLv+og/jK70rwOGXRed2JnKntqfBEnR51gky
 | 
				
			||||||
 | 
					9axyyz3dAMEE1rCc+oOv7ycZoEKwPdXiyneOCLT40QT6No1UrMJCa32a4+YJgbAN
 | 
				
			||||||
 | 
					B8igFwwhdapD5N+qvpCWtiKsdnbPeQIDAQABAoICAALHmEMkqAWbK66QB7UhSe48
 | 
				
			||||||
 | 
					z7l0ImIQrrb1mB59EjHJOD6EiUJfc/2D4tvqYECsgqW3G30saifxWsLjxcpiuTA2
 | 
				
			||||||
 | 
					nhngUGAQD1IZ2pQwpyPkNyQC0b8qaquotZDPhekOmkrJ+Y0AF3D5Mk3+LVPfznz/
 | 
				
			||||||
 | 
					F8XOQ0uTwal7ZfNlyAveNqaYcktcV+hxkQSAfnnHTBpITGCab6in0Rxj24fyCCms
 | 
				
			||||||
 | 
					n5zleaEgOAyIUlPVSh1ZMeaT5eT4/BBdH8mAyXcuqRtMScmgOPMc1Q6m84xblxPA
 | 
				
			||||||
 | 
					JuTHEBwGivPK3Gbvpw7/ftiaSb41gsJnvPr0qjHeQ9jQhLdkk9iKth82oZc18kVg
 | 
				
			||||||
 | 
					ipF1TdSHz1EauoczyHM27aN1ZdPibkaic8QdPya0086sn+uXDRPELivV1xSMSHsH
 | 
				
			||||||
 | 
					xpEuANeL874X5h9Cpv4vWcJnQrbs81C4cXI46Mrc561uKljDVtvYFXvpdZuJ4GNp
 | 
				
			||||||
 | 
					C9zNNLp1ssmME9uLjLYIbmek/shb9XMpn7XhV0poWUZPGijI7qGLe6OoOqXdKoes
 | 
				
			||||||
 | 
					KMXkVJ5omfd/GvvmisJQaFcstqPO54MscFm4cBXQ0U+DxGT0QtSNi4YHtNs8EMdw
 | 
				
			||||||
 | 
					2AYlLN/DIzIm+YeR+rWNf8TYZbS1CazQj/ee4DTPAprKsumaR8/Cw+ACl6ICpUFA
 | 
				
			||||||
 | 
					bHMCd65TcV94F+LU7L5VAoIBAQDv8oPAUMeaFpY524h9k33HlNmvrmA5aF9tbeEp
 | 
				
			||||||
 | 
					b0QJpisldK8w8Rx9/7PS3NP5DO2z1GbNW8+iZE+QH03fIa1QeNBWISnfK8VUkUHn
 | 
				
			||||||
 | 
					8j6Q52O0bxC2v+a76U0MdP4JqfrihuHXvjH++9FN/KVwpAJlj7Fq8HugymEpi8+Y
 | 
				
			||||||
 | 
					Xv4VnzSm/sdbThvbSHzSGo8Y38dbN7pM6tOen36mxcAnOlH6GnTFEWYmo/f5jj8b
 | 
				
			||||||
 | 
					I/+rI8pmeDK6HPZFXw8FonEykX2My8OrN4iGLkFqlFfdgXHtuuPDLImxOCiJN0y7
 | 
				
			||||||
 | 
					bizq412/kh7Fbg7Q3oSULd9tmojVi3em4QWvxlxbOwIXjyT1AoIBAQDDLnOsvy2G
 | 
				
			||||||
 | 
					ajFvKJ3bSrh3OQdGFyJn0nquZtgzDXsatrItaBYZtUIqnRsfjQZqyvoYNRDqs9QR
 | 
				
			||||||
 | 
					xmqB7guPkqLN/mk+mAjmHWPs0oP0Y9S2IXl5/CRIuM3ZcVTVVsPC8lOrXAH3X1jZ
 | 
				
			||||||
 | 
					OJiUG/fUUJoonDPnFZLGajefmFsUWjyIr85VOUMhYsq2lA3ZTyM6rQLX3gM//36u
 | 
				
			||||||
 | 
					d70K1kXPWoWIsbaztPpqBSJK05EjztVmkUYbPKqHVz+8TD4Xr1baSC1Q0KuHqrr1
 | 
				
			||||||
 | 
					451biNN/TSG5GOgdJRZcVXh0imp+xQjB3x2UmwNKk4uRXRWnoa0QlhKm0kbapaGP
 | 
				
			||||||
 | 
					QVCUgwlQOA31AoIBAGmvhbx1WBVUkYKWYX3+Ms5vj5pD0fo3MKEAXsZjTbJ6UFLF
 | 
				
			||||||
 | 
					HE0QRh5xPAFKZssxmJk2mrklEUVTrX+rah83tCDXtdvZ65lyrA3dlQvWtRwZ7t6Q
 | 
				
			||||||
 | 
					dOopiDWIQvmTpjkXd3vDMUJXcan/vGb/OtdsRen56olRtwJRYY5tGFjirkNTxlsv
 | 
				
			||||||
 | 
					qRtcQgTJ3sCkFhc8qZBR8Wrjm6YoVh6ax1H/7A+fC4OpcDbgzd5Lexw3NOtqbkHH
 | 
				
			||||||
 | 
					+3/iNc7EWdd/fyBo2MXlEiAd67I+OW36POFBnK67PIrA2T0HoUMe6ls74ejrkGVK
 | 
				
			||||||
 | 
					tOb83OW+vOKPefPKty5nqaIFRv3u/sroKLm7wOkCggEAFBsR4WakKud/hiLZ9///
 | 
				
			||||||
 | 
					dpCSVj8F1UoSRyri9Idb+gl92z2QoT9RvJAIfjyJv7B/CMVWo8a4fshAqne6CyUg
 | 
				
			||||||
 | 
					zjV54+/HYuT+KSQaYa9y9vwFxnIZzr/yvIZ3Ja7VZZyOz+UfcrsIrP+uf/tNkTpo
 | 
				
			||||||
 | 
					VuyYUCKhxvykFDWelD8jYzUw/Qh0CNljZmFj99G2IFI4K8J79Ti9dP1ypM4jzNNX
 | 
				
			||||||
 | 
					VBhyaJqo/QjgWnLmzZh91R376cxbCKwNLblw4AG44a1ztZJ5SPVmYvP6frZeiwuI
 | 
				
			||||||
 | 
					AMg3COGMJyDK0r57b+meGFKCeo9pTGJcizHajDUUXdQHwdWBZP6Q4O/qfBHvgKr1
 | 
				
			||||||
 | 
					jQKCAQEA4UaBpHUcO9TG5NEMX+IOMurcuYnlf+12ImGix21A2ylOI7RIfA/RCfgK
 | 
				
			||||||
 | 
					7UAwT9OqTNhvgJ9DCth7y6TJ6/4UnKJ1duaM7sP6vX3Vq8z0zixYDZJ2bE4COgBJ
 | 
				
			||||||
 | 
					tzAOLM22cpIJj98XhCdMOzkVse7vQDpBJPmTh19pqfuFnGLmsIIdLuo64Xa+6bvB
 | 
				
			||||||
 | 
					p21edHgxH1pl82rfnvMTMzoicH0mQZQD+l19O6togwhpJY1YbPaqGlCavlQqMKyC
 | 
				
			||||||
 | 
					r8fseEBic1de7Y9XaG25TS+lZVg53vOB2BNZM6Z8CjeRf3rdZZd+cCqa7aFsdmER
 | 
				
			||||||
 | 
					hfHYKzHGaDbp/aPWH8HQzfs6QxGRog==
 | 
				
			||||||
 | 
					-----END PRIVATE KEY-----
 | 
				
			||||||
							
								
								
									
										25
									
								
								shell.nix
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										25
									
								
								shell.nix
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					{ pkgs ? import <nixpkgs> {}, lib ? pkgs.lib }:
 | 
				
			||||||
 | 
					pkgs.mkShellNoCC {
 | 
				
			||||||
 | 
						packages = with pkgs; [ rustup nats-server caddy postgresql clang pkg-config tmux /*you'll *need* tmux*/ ];
 | 
				
			||||||
 | 
						buildInputs = with pkgs; [ openssl clang foundationdb ];
 | 
				
			||||||
 | 
						LIBCLANG_PATH = lib.makeLibraryPath [ pkgs.libclang ];
 | 
				
			||||||
 | 
						shellHook = ''
 | 
				
			||||||
 | 
							rustup install stable
 | 
				
			||||||
 | 
							rustup default stable
 | 
				
			||||||
 | 
							export RUST_LOG=debug
 | 
				
			||||||
 | 
							export NATS_URL="127.0.0.1:4222"
 | 
				
			||||||
 | 
							export NATS_CERT=$(cat cert.pem)
 | 
				
			||||||
 | 
							export NATS_KEY=$(cat key.pem)
 | 
				
			||||||
 | 
							export ASKLYPHE_URL="http://127.0.0.1:8002"
 | 
				
			||||||
 | 
							export AUTH_URL="http://127.0.0.1:8001"
 | 
				
			||||||
 | 
							export DB_URL="postgres://127.0.0.1:5432/user"
 | 
				
			||||||
 | 
							export SMTP_DISABLE=1
 | 
				
			||||||
 | 
							export SMTP_USERNAME=""
 | 
				
			||||||
 | 
							export SMTP_PASSWORD=""
 | 
				
			||||||
 | 
							export SMTP_URL=""
 | 
				
			||||||
 | 
							export POSTGRESQL_PASSWORD="user"
 | 
				
			||||||
 | 
							# lmao
 | 
				
			||||||
 | 
							echo WARNING: RUSTFLAGS="-A dead_code -A unused"
 | 
				
			||||||
 | 
							export RUSTFLAGS="-A dead_code -A unused"
 | 
				
			||||||
 | 
						'';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue