Table endpoint for generating a truth table from a string expression

This commit is contained in:
Martin Berg Alstad 2024-06-17 00:21:18 +02:00
parent d0198eab5d
commit 6b6f4b4779
7 changed files with 85 additions and 48 deletions

View File

@ -131,3 +131,13 @@ GET {{url}}/simplify/{{expression}}
### GET with simplify="true"
GET {{url}}/simplify/A?simplify=true&hide=NONE&sort=DEFAULT&caseSensitive=false&hideIntermediate=false
### GET only table
GET {{url}}/table/A
> {%
client.test("Response body contains only the truth table", () => {
client.assert(response.body.truthTable, "Response body does not contain the truth table")
});
%}

View File

@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::expressions::expression::Expression;
use crate::map;
use crate::routing::options::TruthTableOptions;
use crate::utils::array::Distinct;
type TruthMatrix = Vec<Vec<bool>>;
@ -34,12 +35,6 @@ pub enum Sort {
FalseFirst,
}
#[derive(Debug, Default, Deserialize)]
pub struct TruthTableOptions {
pub sort: Sort,
pub hide: Hide,
}
impl TruthTable {
pub fn new(expression: &Expression, options: TruthTableOptions) -> Self {
let header = Self::extract_header(expression);

View File

@ -1,3 +1,4 @@
pub(crate) mod response;
mod error;
pub(crate) mod routes;
pub(crate) mod error;
pub(crate) mod routes;
pub(crate) mod options;

34
src/routing/options.rs Normal file
View File

@ -0,0 +1,34 @@
use serde::Deserialize;
use crate::expressions::truth_table::{Hide, Sort};
use crate::utils::serialize::{ret_true, deserialize_bool};
#[derive(Deserialize)]
pub struct SimplifyOptions {
#[serde(
default = "ret_true",
deserialize_with = "deserialize_bool"
)]
pub simplify: bool,
#[serde(default = "ret_true")]
pub case_sensitive: bool, // TODO: Implement case sensitivity
}
#[derive(Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct TruthTableOptions {
#[serde(default)]
pub sort: Sort,
#[serde(default)]
pub hide: Hide,
#[serde(default)]
pub hide_intermediate_steps: bool, // TODO: Implement hide intermediate steps
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SimplifyAndTableOptions {
#[serde(flatten)]
pub simplify_options: SimplifyOptions,
#[serde(flatten)]
pub table_options: TruthTableOptions,
}

View File

@ -1,6 +1,6 @@
use axum::Json;
use axum::response::{IntoResponse, Response};
use serde::{Deserialize, Serialize};
use serde::Serialize;
use crate::expressions::expression::Expression;
use crate::expressions::simplify::Law;
@ -56,6 +56,7 @@ pub struct SimplifyResponse {
pub truth_table: Option<TruthTable>,
}
// TODO derive macro
impl IntoResponse for SimplifyResponse {
fn into_response(self) -> Response {
BaseResponse::create(self)
@ -72,4 +73,16 @@ impl IntoResponse for IsLegalResponse {
fn into_response(self) -> Response {
BaseResponse::create(self)
}
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TruthTableResponse {
pub truth_table: TruthTable,
}
impl IntoResponse for TruthTableResponse {
fn into_response(self) -> Response {
BaseResponse::create(self)
}
}

View File

@ -2,13 +2,12 @@ use axum::{Router, routing::get};
use axum::extract::{Path, Query};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use serde::{Deserialize};
use crate::expressions::expression::Expression;
use crate::expressions::truth_table::{Hide, Sort, TruthTable, TruthTableOptions};
use crate::expressions::truth_table::TruthTable;
use crate::routing::error::{Error, ErrorKind};
use crate::routing::options::{SimplifyAndTableOptions, SimplifyOptions};
use crate::routing::response::SimplifyResponse;
use crate::utils::serialize::{ret_true, deserialize_bool};
pub fn router() -> Router<()> {
Router::new()
@ -19,17 +18,6 @@ pub fn router() -> Router<()> {
)
}
#[derive(Deserialize)]
struct SimplifyOptions {
#[serde(
default = "ret_true",
deserialize_with = "deserialize_bool"
)]
simplify: bool,
#[serde(default = "ret_true")]
case_sensitive: bool, // TODO: Implement case sensitivity
}
async fn simplify(Path(path): Path<String>, Query(query): Query<SimplifyOptions>) -> Response {
match Expression::try_from(path.as_str()) {
Ok(mut expression) => {
@ -52,20 +40,7 @@ async fn simplify(Path(path): Path<String>, Query(query): Query<SimplifyOptions>
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct SimplifyAndTableQuery {
#[serde(flatten)]
simplify_options: SimplifyOptions,
#[serde(default)]
sort: Sort,
#[serde(default)]
hide: Hide,
#[serde(default)]
hide_intermediate_steps: bool, // TODO
}
async fn simplify_and_table(Path(path): Path<String>, Query(query): Query<SimplifyAndTableQuery>) -> Response {
async fn simplify_and_table(Path(path): Path<String>, Query(query): Query<SimplifyAndTableOptions>) -> Response {
match Expression::try_from(path.as_str()) {
Ok(mut expression) => {
let before = expression.to_string();
@ -73,10 +48,7 @@ async fn simplify_and_table(Path(path): Path<String>, Query(query): Query<Simpli
if query.simplify_options.simplify {
(expression, operations) = expression.simplify();
}
let truth_table = TruthTable::new(&expression, TruthTableOptions {
sort: query.sort,
hide: query.hide,
});
let truth_table = TruthTable::new(&expression, query.table_options);
SimplifyResponse {
before,
after: expression.to_string(),

View File

@ -1,16 +1,28 @@
use axum::body::Body;
use axum::response::Response;
use axum::extract::{Path, Query};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Router;
use axum::routing::post;
use axum::routing::get;
use crate::expressions::expression::Expression;
use crate::expressions::truth_table::TruthTable;
use crate::routing::error::{Error, ErrorKind};
use crate::routing::options::TruthTableOptions;
use crate::routing::response::TruthTableResponse;
pub fn router() -> Router<()> {
Router::new()
.nest("/table", Router::new()
.route("/", post(table)),
.route("/:exp", get(table)),
)
}
// TODO Json Deserialize not working on Axum? Manually parse the body?
async fn table(body: Body) -> Response {
unimplemented!()
// TODO Expression as input in body
async fn table(Path(value): Path<String>, Query(query): Query<TruthTableOptions>) -> Response {
match Expression::try_from(value) {
Ok(expression) => {
TruthTableResponse { truth_table: TruthTable::new(&expression, query) }.into_response()
}
Err(e) => (StatusCode::BAD_REQUEST, Error::new(e.to_string(), ErrorKind::InvalidExpression)).into_response(),
}
}