Skip to content

Commit

Permalink
Merge pull request #80 from jabibamman/feat/server-fragment_result
Browse files Browse the repository at this point in the history
Feat - server fragment result
  • Loading branch information
jabibamman authored Feb 23, 2024
2 parents faee5a0 + 22f3d7f commit 8119e8d
Show file tree
Hide file tree
Showing 23 changed files with 452 additions and 132 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,42 @@ To generate documentation for all packages including dependencies:
cargo doc --open
```

## CLI Arguments

Represents command line arguments the CLI application

### Client arguments

```bash
Usage: client [OPTIONS]

Options:

--hostname <HOSTNAME> Optional: The hostname of the client. Default: "localhost" [default: localhost]
-P, --port <PORT> Optional: The port number to connect on. Default: 8787 [default: 8787]
-N, --name <WORKER_NAME> Optional: The name of the worker. Default: "worker" [default: worker]
-v, --verbose Optional: Add a flag to enable/disable logging. Default: false
-d, --debug Optional: Add a flag to enable/disable debug mode. Default: false
-o, --open Optional: Add a flag to enable/disable opening the browser. Default: false
-s, --save Optional: Add a flag to save the image to a file. Default: false
-h, --help Print help (see more with '--help')
```

### Server arguments

```bash
Usage: server [OPTIONS]

Options:
--hostname <HOSTNAME> The hostname of the server. Default: "localhost" [default: localhost]
-P, --port <PORT> The port number the server listens on. Default: 8787 [default: 8787]
-v, --verbose Optional: Add a flag to enable/disable logging. Default: false
-d, --debug Optional: Add a flag to enable/disable debug mode. Default: false
--width <WIDTH> Optional: Add a flag to edit the width and height of the window. Default: 1200 [default: 1200]
--height <HEIGHT> Optional: Add a flag to edit the width and height of the window. Default: 1200 [default: 1200]
-h, --help Print help (see more with '--help')
```

## Contributing

Contributions are welcome. Please follow standard contribution guidelines for pull requests.
4 changes: 4 additions & 0 deletions cli/src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ mod operation_tests {
port: 8787,
verbose: false,
debug: false,
width: 1,
height: 1,
}
}

Expand Down Expand Up @@ -36,6 +38,8 @@ mod operation_tests {
port: args.port.clone(),
verbose: args.verbose.clone(),
debug: args.debug.clone(),
width: 1,
height: 1,
};

let address = format!("{}:{}", server_args.hostname, server_args.port);
Expand Down
18 changes: 16 additions & 2 deletions cli/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub use clap::Parser;
pub struct CliClientArgs {
/// Optional: The hostname of the client.
/// Default: "localhost"
#[clap(short = 'H', long = "hostname", default_value = "localhost")]
#[clap(long = "hostname", default_value = "localhost")]
pub hostname: String,

/// Optional: The port number to connect on.
Expand Down Expand Up @@ -61,6 +61,10 @@ pub struct CliClientArgs {
/// ## Fields
/// - `hostname`: A string specifying the hostname. Defaults to "localhost".
/// - `port`: A 16-bit unsigned integer specifying the port number. Defaults to 8787.
/// - `verbose`: A boolean flag to enable/disable logging. Defaults to false.
/// - `debug`: A boolean flag to enable/disable debug mode. Defaults to false.
/// - `width`: A 16-bit unsigned integer specifying the width of the window. Defaults to 1200.
/// - `height`: A 16-bit unsigned integer specifying the height of the window. Defaults to 1200.
///
/// ## Example
/// Command line usage for the server might be:
Expand All @@ -71,7 +75,7 @@ pub struct CliClientArgs {
pub struct CliServerArgs {
/// The hostname of the server.
/// Default: "localhost"
#[clap(short = 'H', long = "hostname", default_value = "localhost")]
#[clap(long = "hostname", default_value = "localhost")]
pub hostname: String,

/// The port number the server listens on.
Expand All @@ -88,6 +92,16 @@ pub struct CliServerArgs {
/// Default: false
#[clap(short = 'd', long = "debug", default_value = "false")]
pub debug: bool,

/// Optional: Add a flag to edit the width and height of the window.
/// Default: 1200
#[clap(long = "width", default_value = "1200")]
pub width: u16,

/// Optional: Add a flag to edit the width and height of the window.
/// Default: 1200
#[clap(long = "height", default_value = "1200")]
pub height: u16,
}

/// An enumeration representing the possible types of command line arguments.
Expand Down
84 changes: 3 additions & 81 deletions client/src/fractal_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use complex::complex_operations::ComplexOperations;
use complex::fractal_operations::FractalOperations;
use image::{ImageBuffer, Rgb};
use log::info;
use shared::types::color::{HSL, RGB};
use shared::types::complex::Complex;
use shared::types::error::FractalError;
use shared::types::fractal_descriptor::FractalType::{
BurningShip, IteratedSinZ, Julia, Mandelbrot, NewtonRaphsonZ3, NewtonRaphsonZ4,
};
use shared::types::messages::FragmentTask;
use shared::types::pixel_intensity::PixelIntensity;
use shared::utils::colors_utils::color;

/// Generates an image of a Fractal Type based on the provided fragment task.
///
Expand Down Expand Up @@ -41,10 +41,7 @@ pub fn generate_fractal_set(
let scale_y = (range.max.y - range.min.y) / resolution.ny as f64;

let mut img = ImageBuffer::new(resolution.nx.into(), resolution.ny.into());

let mut pixel_data_vec = Vec::new();

// crée une matrice de pixel_intensity
let mut pixel_matrice_intensity = Vec::new();

info!("Generating fractal set...");
Expand All @@ -55,11 +52,8 @@ pub fn generate_fractal_set(

let pixel_intensity =
descriptor.compute_pixel_intensity(&complex_point, fragment_task.max_iteration);
if pixel_intensity.count != 1.0 {
*pixel = Rgb(color(pixel_intensity));
} else {
*pixel = Rgb([0, 0, 0]);
}

*pixel = Rgb(color(pixel_intensity));

pixel_matrice_intensity.push(pixel_intensity);
pixel_data_vec.push(pixel[0]);
Expand All @@ -70,57 +64,6 @@ pub fn generate_fractal_set(
Ok((img, pixel_data_vec, pixel_matrice_intensity))
}

///Generates a color based on the provided pixel intensity.
/// # Arguments
/// * `pixel_intensity`: A `PixelIntensity` containing the number of iterations and the norm of the complex point.
///
/// # Returns
/// Returns an array containing the RGB values of the color.
///
fn color(pixel_intensity: PixelIntensity) -> [u8; 3] {
let hsl = HSL {
h: pixel_intensity.count * 360.0,
s: 0.5 + 0.5 * (pixel_intensity.zn * 3.14).cos(),
l: 0.5,
};

let color = hsl_to_rgb(hsl);

[color.r, color.g, color.b]
}

/// Convert a color from HSL to RGB
/// # Arguments
/// * `hsl`: A `HSL` containing the HSL values of the color (Hue, Saturation, Lightness)
///
/// # Returns
/// Returns a tuple containing the RGB values of the color
///
/// # Details
/// This function is based on the algorithm found at https://www.rapidtables.com/convert/color/hsl-to-rgb.html
///
fn hsl_to_rgb(hsl: HSL) -> RGB {
let c = (1.0 - (2.0 * hsl.l - 1.0).abs()) * hsl.s;
let h_prime = hsl.h / 60.0;
let x = c * (1.0 - (h_prime % 2.0 - 1.0).abs());
let m = hsl.l - c / 2.0;

let (r_temp, g_temp, b_temp) = match h_prime.floor() as u8 {
0 => (c, x, 0.0),
1 => (x, c, 0.0),
2 => (0.0, c, x),
3 => (0.0, x, c),
4 => (x, 0.0, c),
_ => (c, 0.0, x),
};

RGB {
r: ((r_temp + m) * 255.0) as u8,
g: ((g_temp + m) * 255.0) as u8,
b: ((b_temp + m) * 255.0) as u8,
}
}

#[cfg(test)]
mod julia_descriptor_tests {
use complex::complex_operations::ComplexOperations;
Expand All @@ -135,7 +78,6 @@ mod julia_descriptor_tests {
use shared::types::range::Range;
use shared::types::resolution::Resolution;
use shared::types::u8data::U8Data;
use shared::utils::type_of::type_of;

use super::*;

Expand Down Expand Up @@ -284,24 +226,4 @@ mod julia_descriptor_tests {
assert_eq!(img.dimensions(), (800, 600));
}
}

#[test]
fn test_color() {
let pixel_intensity = PixelIntensity {
zn: 0.5,
count: 0.5,
};

let result = color(pixel_intensity);

let test0 = type_of(result[0]);
let test1 = type_of(result[1]);
let test2 = type_of(result[2]);

assert!(test0.eq("u8"));
assert!(test1.eq("u8"));
assert!(test2.eq("u8"));

assert_eq!(result, [63, 191, 191]);
}
}
3 changes: 2 additions & 1 deletion client/src/networking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ pub fn process_fragment_task(
) -> Result<TcpStream, FractalError> {
let dir_path_buf = get_dir_path_buf()?;

let img_path = get_file_path("julia", dir_path_buf, get_extension_str(FileExtension::PNG))?;
let img_path: String =
get_file_path("julia", dir_path_buf, get_extension_str(FileExtension::PNG))?;
let (img, pixel_data_bytes, pixel_intensity_matrice) = generate_fractal_set(task.clone())?;

debug!("Pixel data bytes: {:?}", pixel_data_bytes);
Expand Down
1 change: 0 additions & 1 deletion server/src/image.rs

This file was deleted.

1 change: 0 additions & 1 deletion server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod image;
pub mod messages;
pub mod services;
pub use serde::{Deserialize, Serialize};
4 changes: 4 additions & 0 deletions server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::env;

use cli::parser::{CliServerArgs, Parser};
use log::{error, info};
use server::services::server_runner::run_server;
Expand All @@ -6,6 +8,8 @@ use shared::types::error::FractalError;
fn main() -> Result<(), FractalError> {
let cli_args: CliServerArgs = CliServerArgs::parse();
shared::logger::init_logger(cli_args.verbose, cli_args.debug)?;
env::set_var("RESOLUTION_WIDTH", cli_args.width.to_string());
env::set_var("RESOLUTION_HEIGHT", cli_args.height.to_string());

let address = format!("{}:{}", cli_args.hostname, cli_args.port);
match run_server(address.as_str()) {
Expand Down
79 changes: 57 additions & 22 deletions server/src/messages/fragment_maker.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,72 @@
use std::error::Error;

use shared::types::fractal_descriptor::FractalType::IteratedSinZ;
use shared::types::{
complex::Complex,
fractal_descriptor::{FractalDescriptor, IteratedSinZDescriptor},
messages::{FragmentRequest, FragmentResult, FragmentTask},
messages::{FragmentResult, FragmentTask},
point::Point,
range::Range,
resolution::Resolution,
u8data::U8Data,
};
use shared::utils::env_utils::get_env_var_as_u16;

pub fn create_tasks() -> Result<Vec<FragmentTask>, Box<dyn Error>> {
let width = get_env_var_as_u16("RESOLUTION_WIDTH")?;
let height = get_env_var_as_u16("RESOLUTION_HEIGHT")?;

let range = generate_range(
Range::new(Point::new(-3.0, -3.0), Point::new(3.0, 3.0)),
2.0,
);
let mut tasks = vec![];

pub fn create_task_for_request(_request: FragmentRequest) -> FragmentTask {
FragmentTask {
id: U8Data {
offset: 0,
count: 16,
},
fractal: FractalDescriptor {
fractal_type: IteratedSinZ(IteratedSinZDescriptor {
c: Complex { re: 0.2, im: 1.0 },
}),
},
max_iteration: 64,
resolution: Resolution { nx: 1080, ny: 1920 },
range: Range {
min: Point {
x: -2.0,
y: -3.55556,
for r in range {
let task = FragmentTask {
id: U8Data {
offset: 0,
count: 16,
},
fractal: FractalDescriptor {
fractal_type: IteratedSinZ(IteratedSinZDescriptor {
c: Complex { re: 0.2, im: 1.0 },
}),
},
max_iteration: 64,
resolution: Resolution {
nx: width,
ny: height,
},
max: Point { x: 2.0, y: 3.55556 },
},
range: r,
};

tasks.push(task);
}

Ok(tasks)
}

pub fn process_result(_result: FragmentResult) {
todo!()
pub fn process_result(_result: FragmentResult) {}

pub fn generate_range(full_image: Range, step: f64) -> Vec<Range> {
let mut ranges = Vec::new();
let y_step = step;
let x_step = step;

let mut y = full_image.min.y;
while y < full_image.max.y {
let mut x = full_image.min.x;
while x < full_image.max.x {
let min = Point::new(x, y);
let max = Point::new(
(x + x_step).min(full_image.max.x),
(y + y_step).min(full_image.max.y),
);
ranges.push(Range::new(min, max));
x += x_step;
}
y += y_step;
}
ranges
}
Loading

0 comments on commit 8119e8d

Please sign in to comment.