Skip to content

Commit

Permalink
Merge pull request #19 from sebastienrousseau/feature/mini-functions
Browse files Browse the repository at this point in the history
Feature/mini functions
  • Loading branch information
sebastienrousseau authored Jan 5, 2023
2 parents 3daa6b1 + dd4aef6 commit 57a97a6
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"ABCDEFGHIJKLMNOP",
"binutils",
"certutil",
"congruential",
"czvf",
"datetime",
"dylib",
Expand All @@ -24,6 +25,7 @@
"rustup",
"Seedable",
"softprops",
"struct",
"Swatinem",
"uuid",
"Zellers"
Expand Down
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ readme = "README.md"
repository = "https://github.com/sebastienrousseau/mini-functions.git"
resolver = "2" # Enables the new Cargo resolution engine
rust-version = "1.57.0"
version = "0.0.4"
version = "0.0.5"

[badges]
maintenance = { status = "actively-developed" }
Expand All @@ -32,9 +32,6 @@ qrcode = "0.12.0"
time = "0.3.17"
uuid = { version = "1.2.2", features = ["v3", "v4", "v5"] }

[build-dependencies]
cross = "0.2.4"

[lib]
name = "mini_functions"
path = "src/lib.rs"
Expand Down
47 changes: 33 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Add the following to your `Cargo.toml` file:

```toml
[dependencies]
mini-functions = "0.0.4"
mini-functions = "0.0.5"
```

## Usage 📖
Expand All @@ -91,9 +91,16 @@ of data.

The `mini-functions` library consists of the following functions:

- [Date and time functions](#date-and-time-functions)
- [Log functions](#log-functions)
- [UUID functions](#uuid-functions)
- The **[Date and time functions](#date-and-time-functions)** are used
to retrieve and manipulate information about dates and times.
- The **[Log functions](#log-functions)** are used to log messages to
the console.
- The **[QRCode functions](#qrcode-functions)** are used to generate
QRCode images and data.
- The **[Random number functions](#random-number-functions)** are used
to generate random numbers in a variety of sizes and formats.
- The **[UUID functions](#uuid-functions)** are used to generate UUIDs
(Universally Unique Identifiers).

The following tables provide a brief description of each function in the
`mini-functions` library.
Expand Down Expand Up @@ -124,15 +131,6 @@ The following tables provide a brief description of each function in the
| `Log::log()` | `log.rs` | `fn log()` | Logs a message to the console.|
| `Log::new()` | `log.rs` | `fn new()` | Creates a new log instance. |

### UUID functions

| Function | Include File | Function Prototype | Description |
| -------- | ------------ | ------------------ | ----------- |
| `UUID::new()` | `uuid.rs` | `fn new()` | Creates a new UUID instance based on the version specified. (v3, v4, v5) |
| `UUID::uuid_v3()` | `uuid.rs` | `fn uuid_v3()` | Creates a new UUID v3 instance. |
| `UUID::uuid_v4()` | `uuid.rs` | `fn uuid_v4()` | Creates a new UUID v4 instance. |
| `UUID::uuid_v5()` | `uuid.rs` | `fn uuid_v5()` | Creates a new UUID v5 instance. |

### QRCode functions

| Function | Include File | Function Prototype | Description |
Expand All @@ -146,6 +144,27 @@ The following tables provide a brief description of each function in the
| `QRCode::to_qrcode()` | `qrcode.rs` | `fn to_qrcode()` | Converts the QRCode instance to a QRCode image. |
| `QRCode::to_svg()` | `qrcode.rs` | `fn to_svg()` | Converts the QRCode instance to a SVG image. |

### Random number functions

| Function | Include File | Function Prototype | Description |
| -------- | ------------ | ------------------ | ----------- |
| `Random::bytes()` | `random.rs` | `fn bytes()` | Generates a vector of random bytes of a given length. |
| `Random::default()` | `random.rs` | `fn default()` | Creates a new `Random` struct with a default seed. |
| `Random::float()` | `random.rs` | `fn float()` | Generates a random floating point number between 0 and 1. |
| `Random::int()` | `random.rs` | `fn int()` | Generates a random integer between a minimum and maximum value. |
| `Random::new()` | `random.rs` | `fn new()` | Creates a new `Random` struct with a seed based on the current system time. |
| `Random::pseudo()` | `random.rs` | `fn pseudo()` | Generates a pseudo-random number by XORing the last 31 random numbers together. |
| `Random::random()` | `random.rs` | `fn random()` | Generates a random number using the linear congruential generator algorithm. The multiplier for the algorithm is the golden ratio. |

### UUID functions

| Function | Include File | Function Prototype | Description |
| -------- | ------------ | ------------------ | ----------- |
| `UUID::new()` | `uuid.rs` | `fn new()` | Creates a new UUID instance based on the version specified. (v3, v4, v5) |
| `UUID::uuid_v3()` | `uuid.rs` | `fn uuid_v3()` | Creates a new UUID v3 instance. |
| `UUID::uuid_v4()` | `uuid.rs` | `fn uuid_v4()` | Creates a new UUID v4 instance. |
| `UUID::uuid_v5()` | `uuid.rs` | `fn uuid_v5()` | Creates a new UUID v5 instance. |

![divider][divider]

## Semantic Versioning Policy 🚥
Expand Down Expand Up @@ -195,6 +214,6 @@ for their help and support.
[crates-badge]: https://img.shields.io/crates/v/mini-functions.svg?style=for-the-badge 'Crates.io'
[divider]: https://raw.githubusercontent.com/sebastienrousseau/vault/main/assets/elements/divider.svg "divider"
[docs-badge]: https://img.shields.io/docsrs/mini-functions.svg?style=for-the-badge 'Docs.rs'
[libs-badge]: https://img.shields.io/badge/lib.rs-0.0.1-orange.svg?style=for-the-badge 'Lib.rs'
[libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.5-orange.svg?style=for-the-badge 'Lib.rs'
[license-badge]: https://img.shields.io/crates/l/mini-functions.svg?style=for-the-badge 'License'
[mwl]: https://raw.githubusercontent.com/sebastienrousseau/vault/main/assets/shields/made-with-love.svg "Made With Love"
87 changes: 87 additions & 0 deletions examples/random.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use mini_functions::random::Random;

// Defining an example for a simple `A Three Card Draw Poker Game` that
// shuffles a deck of cards and allows the user to draw cards from the
// top of the deck, displaying the card name and suit as a string.

// A struct that represents a deck of playing cards
struct Deck {
// A vector of cards
cards: Vec<usize>,
// A random number generator
rng: Random,
}

// Implementation of the `Deck` struct
impl Deck {
// Creates a new `Deck` struct with a shuffled deck of cards
fn new() -> Self {
let mut deck = Self {
cards: (0..52).collect(),
rng: Random::new(),
};

// Shuffle the deck using the Fisher-Yates algorithm
for i in (1..52).rev() {
let j = deck.rng.random() as usize % (i + 1);
deck.cards.swap(i, j);
}
deck
}

// Draws a card from the top of the deck
fn draw(&mut self) -> Option<String> {
let card = self.cards.pop();
if let Some(card) = card {
let suits = ["Spades (♠)", "Clubs (♣)", "Hearts (♥)", "Diamonds (♦)"];
let ranks = [
"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace",
];
let suit = suits[card / 13];
let rank = ranks[card % 13];
Some(format!("{} of {}", rank, suit))
} else {
None
}
}
}

fn main() {
// Create a new random number generator
let mut rng = Random::new();
println!("🦀 Random::new(): ✅ {}", rng);

let default = Random::default();
println!("🦀 Random::default(): ✅ {}", default);

let random = rng.random();
println!("🦀 Random::random(): ✅ {}", random);

let pseudo = rng.pseudo();
println!("🦀 Random::pseudo(): ✅ {}", pseudo);

let bytes = rng.bytes(10);
println!("🦀 Random::bytes(): ✅ {:?}", bytes);

let float = rng.random() as f32 / 0x7FFF as f32;
println!("🦀 Random::float(): ✅ {}", float);

let int = rng.random() as usize;
println!("🦀 Random::int(): ✅ {}", int);

// Create a new deck of cards and draw three cards
let mut deck = Deck::new();

// Draw three cards from the top of the deck and print them to the console
let card1 = deck.draw().unwrap();
let card2 = deck.draw().unwrap();
let card3 = deck.draw().unwrap();

// Print the cards to the console
println!(
"\n🦀 Let's play a mini game of `Three Card Draw Poker` to demonstrate the random number generator!\n"
);
println!("🎲 Deck::draw(): ✅ {}", card1);
println!("🎲 Deck::draw(): ✅ {}", card2);
println!("🎲 Deck::draw(): ✅ {}", card3);
}
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
//! Add the following to your `Cargo.toml` file:
//! ```toml
//! [dependencies]
//! mini_functions = "0.0.4"
//! mini_functions = "0.0.5"
//! ```
//! Then, add the following to your crate root:
//! ```rust
Expand Down Expand Up @@ -73,5 +73,8 @@ pub mod log;
/// Provides a set of utility functions for generating QR codes
pub mod qrcode;

/// Provides a set of utility functions for working with random numbers
pub mod random;

/// Provides a set of utility functions for working with UUIDs
pub mod uuid;
91 changes: 91 additions & 0 deletions src/random.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//! # Core random number generator
//!
//! This crate provides a random number generator based on the linear congruential generator algorithm with the golden ratio as the multiplier.
//!
//!
// Copyright © 2022-2023 Mini Functions. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use std::time::SystemTime;

/// A random number generator based on the linear congruential generator
/// algorithm with the golden ratio as the multiplier.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct Random {
// The seed for the random number generator
seed: u32,
}

impl Random {
/// Creates a new `Random` struct with a seed based on the current
/// system time.
pub fn new() -> Self {
// Get the current system time in milliseconds
let seed = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_millis() as u32;
Self { seed }
}

/// Generates a random number using the linear congruential
/// generator algorithm. The multiplier for the algorithm is the
/// golden ratio.
pub fn random(&mut self) -> u32 {
// The multiplier for the linear congruential generator
// algorithm
let golden_ratio = 1140071478;
// Update the seed with the next value in the sequence
self.seed = self.seed.wrapping_mul(golden_ratio).wrapping_add(12345);
// Return the upper 15 bits of the seed as the random number
(self.seed >> 16) & 0x7FFF
}

/// Generates a pseudo-random number by XORing the last 31 random
/// numbers together.
pub fn pseudo(&mut self) -> u32 {
let mut res = self.random();
let mut rng = Random::default();
// XOR the last 31 random numbers together to generate the
// pseudo-random number
for _ in 0..31 {
res ^= rng.random();
}
res
}

/// Generates a vector of random bytes of a given length.
pub fn bytes(&mut self, len: usize) -> Vec<u8> {
let mut res = Vec::with_capacity(len);
let mut rng = Random::default();
for _ in 0..len {
res.push(rng.random() as u8);
}
res
}
/// Generates a random floating point number between 0 and 1.
pub fn float(&mut self) -> f32 {
let mut rng = Random::default();
rng.random() as f32 / 0x7FFF as f32
}
/// Generates a random integer between a minimum and maximum value.
pub fn int(&mut self, min: i32, max: i32) -> i32 {
let mut rng = Random::default();
(rng.random() as f32 / 0x7FFF as f32 * (max - min) as f32) as i32 + min
}
}

impl std::fmt::Display for Random {
/// Formats the `Random` struct as a string for display.
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Random {{ seed: {} }}", self.seed)
}
}

impl Default for Random {
fn default() -> Self {
Self::new()
}
}
3 changes: 3 additions & 0 deletions tests/main.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
mod date;
mod log;
mod qrcode;
mod random;
mod uuid;
Loading

0 comments on commit 57a97a6

Please sign in to comment.