docs: api docs for the challenges
cargo devel CI / cargo CI (push) Successful in 1m26s Details

This commit is contained in:
Christoph J. Scherr 2024-09-06 23:27:42 +02:00
parent bfa532cbd2
commit 80631108b3
4 changed files with 77 additions and 7 deletions

View File

@ -1,3 +1,8 @@
//! The first challenge, in which the contestant only needs to connect by TCP to be sent the secret.
//!
//! This challenge is designed to be simple and straightforward, requiring the contestant to only
//! establish a TCP connection to the server to receive the secret.
use async_trait::async_trait;
use libpt::log::{info, warn};
use tokio::io::AsyncWriteExt;
@ -8,13 +13,12 @@ use crate::config::Config;
use crate::has_won;
use crate::vault::VaultRef;
/// This struct holds the configuration and vault for the challenge.
pub struct C1 {
config: Config,
vault: VaultRef,
}
impl C1 {}
#[async_trait]
impl Challenge for C1 {
fn new(config: Config, vault: VaultRef) -> Self {

View File

@ -1,3 +1,9 @@
//! The second challenge, in which the contestant needs to connect by TCP and write a the [u16]
//! `1337` to win.
//!
//! This challenge is designed to be simple and straightforward, but still requires some thinkering
//! for newbies, especially those that sill only think in text.
use anyhow::Result;
use async_trait::async_trait;
use libpt::log::{info, warn};
@ -9,12 +15,18 @@ use crate::config::Config;
use crate::has_won;
use crate::vault::VaultRef;
/// This struct holds the configuration and vault for the challenge.
pub struct C2 {
config: Config,
vault: VaultRef,
}
impl C2 {
/// Trigger the winning mechanism.
///
/// # Errors
///
/// Will error when writing or shutting down the [TcpStream] fails.
async fn win(
vault: &VaultRef,
stream: &mut TcpStream,

View File

@ -1,3 +1,22 @@
//! The third challenge, in which the contestant must answer a series of math questions within a time limit.
//!
//! This challenge requires the contestant to establish a TCP connection to the server and answer a
//! series of math questions that are randomly generated by the server. The contestant must answer
//! [NEEDED_CORRECT] questions correctly within a time limit of [MILLIS_PER_QUESTION] milliseconds
//! per question. If the contestant fails to answer a question correctly or runs out of time, their
//! counter of correct answers will reset.
//!
//! The math questions are generated randomly and have the form "What is x \[op\] y?", where \[op\] is one
//! of the four basic arithmetic operations (+, -, *, /) and x and y are random integers between
//! 0 and 2^16-1.
//!
//! The contestant must send their answers as bytes (not text) over the TCP connection.
//!
//! It is expected that no human can calculate the questions fast enough, so scripting a math
//! solver is needed.
//!
//! See the [sample solution for c3](https://git.cscherr.de/PlexSheep/wooly-vault/src/branch/master/solutions/3.py).
use std::fmt::Display;
use std::net::SocketAddr;
@ -15,8 +34,10 @@ use crate::config::Config;
use crate::has_won;
use crate::vault::VaultRef;
const NEEDED_CORRECT: usize = 16;
pub const NEEDED_CORRECT: usize = 16;
pub const MILLIS_PER_QUESTION: u128 = 200;
/// Signifies the operations that the randomizer can come up with.
#[derive(Copy, Clone)]
enum Operation {
Add,
@ -26,7 +47,10 @@ enum Operation {
}
impl Operation {
pub(crate) fn calc(self, a: i32, b: i32) -> i32 {
/// Calculate the result of two [i32] with this [Operation].
///
/// This will not error from overflows.
pub fn calc(self, a: i32, b: i32) -> i32 {
match self {
Self::Add => a.overflowing_add(b).0,
Self::Sub => a.overflowing_sub(b).0,
@ -63,13 +87,26 @@ impl Distribution<Operation> for Standard {
}
}
/// This struct holds the configuration and vault for the challenge.
pub struct C3 {
config: Config,
vault: VaultRef,
}
impl C3 {
fn mk_question() -> (String, String) {
/// Create a new randomized math question.
///
/// Questions will always have the same structure:
///
/// * "What is x  y?"
///
/// $x$ and $y$ will always be a random integer between 0 and 2^16-1.
///
/// # Returns
///
/// This function returns both the question and the solution to that question as a tuple. The
/// first is the question and the second is the solution.
pub fn mk_question() -> (String, String) {
let mut rng = rand::thread_rng();
let a: i32 = rng.gen_range(0i32..i16::MAX as i32);
let b: i32 = rng.gen_range(0i32..i16::MAX as i32);
@ -81,7 +118,20 @@ impl C3 {
(question, solution)
}
async fn handler(peer: (TcpStream, SocketAddr), vault: &VaultRef) -> Result<()> {
/// Handle a singular contestant
///
/// Messages sent by Wooly Vault [C3] will always be terminated with a newline. [C3] will
/// [randomlly generate questions](Self::mk_question) that the contestant needs to solve in
/// a given time limit. If the contestant fails to correctly answer [NEEDED_CORRECT] questions
/// in the given time limit, their counter of correct answer will reset.
///
/// The time limit is [the amount of required correct answers](NEEDED_CORRECT) times [the
/// milliseconds per question](MILLIS_PER_QUESTION).
///
/// # Errors
///
/// This function will return an error if using the [TcpStream] fails.
pub async fn handler(peer: (TcpStream, SocketAddr), vault: &VaultRef) -> Result<()> {
let mut stream = peer.0;
let addr = peer.1;
let mut correct: usize = 0;
@ -98,7 +148,7 @@ impl C3 {
Self::win(vault, &mut stream, &addr).await?;
break;
}
if last_reset.elapsed().as_millis() > NEEDED_CORRECT as u128 * 200 {
if last_reset.elapsed().as_millis() > NEEDED_CORRECT as u128 * MILLIS_PER_QUESTION {
correct = 0;
debug!("{addr} was too slow, resetting");
stream_write

View File

@ -58,6 +58,10 @@ where
/// # Returns
///
/// A result indicating whether the challenge was successful ended.
///
/// # Errors
///
/// Will error when the challenge errors, for example when the network adress cannot be bound.
async fn serve(self) -> anyhow::Result<()>;
}