Compare commits
15 Commits
dc2fefdae2
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
| a3f495f87b | |||
| 5615622acc | |||
| b96f00c847 | |||
| 85f8e6eded | |||
| 20313de5dc | |||
| 56275c7369 | |||
| baad3d7791 | |||
| 5211266f3a | |||
| 44fd16d9c7 | |||
| 848ec596c6 | |||
| e802c757f7 | |||
| 223b6d1640 | |||
| 7232c56e4e | |||
| 59477c3ea7 | |||
| 88b1cb8076 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
|
**/.venv/**
|
||||||
|
|
||||||
|
|||||||
16
python/admin.py
Normal file
16
python/admin.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import random
|
||||||
|
import socket
|
||||||
|
|
||||||
|
SERVER_IP = "127.0.0.1"
|
||||||
|
PORT = 5901
|
||||||
|
|
||||||
|
input = random.randint(1, 1000)
|
||||||
|
|
||||||
|
# Manually set the starting "input" for the first team
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((SERVER_IP, PORT))
|
||||||
|
# Using "0" as the ID for the very first team's source
|
||||||
|
s.send(f"ADMIN SET 0 {input}".encode()) # Sets the first clue as 80
|
||||||
|
print(f"Input of {input} Set")
|
||||||
|
print(s.recv(1024).decode())
|
||||||
|
s.close()
|
||||||
30
python/team.py
Normal file
30
python/team.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
# Config
|
||||||
|
SERVER_IP = "127.0.0.1" # Change to master server's IP
|
||||||
|
PORT = 5901
|
||||||
|
MY_ID = "1" # Team Number
|
||||||
|
PREV_ID = "0" # Team Number of Team Sending Clue (should be previous team, but in case of abscences)
|
||||||
|
|
||||||
|
# 1. GET: Wait for input
|
||||||
|
print(f"Waiting for Team {PREV_ID}...")
|
||||||
|
while True:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((SERVER_IP, PORT))
|
||||||
|
s.send(f"GET {PREV_ID}".encode())
|
||||||
|
input = s.recv(1024).decode().strip() # Clue is called input in the code
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
if input != "-1": # -1 Means Clue Is Not Yet Sent
|
||||||
|
print(f"Received input: {input}")
|
||||||
|
break
|
||||||
|
|
||||||
|
# 2. TRANSFORM: Do your logic to convert input to output clue, which should also be an integer Number
|
||||||
|
output = int(input) + 42
|
||||||
|
|
||||||
|
# 3. PUT: Send output
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((SERVER_IP, PORT))
|
||||||
|
s.send(f"PUT {MY_ID} {output}".encode())
|
||||||
|
s.close()
|
||||||
|
print(f"Sent output: {output}")
|
||||||
106
src/main.rs
106
src/main.rs
@@ -1,3 +1,105 @@
|
|||||||
fn main() {
|
use std::collections::HashMap;
|
||||||
println!("Hello, world!");
|
use std::sync::Arc;
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio::sync::RwLock; // Use Tokio's async-aware lock
|
||||||
|
|
||||||
|
// Type alias for our shared thread-safe state
|
||||||
|
type Db = Arc<RwLock<HashMap<String, String>>>;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Bind to all interfaces on port 5901
|
||||||
|
let listener = TcpListener::bind("0.0.0.0:5901").await?;
|
||||||
|
let db: Db = Arc::new(RwLock::new(HashMap::new()));
|
||||||
|
|
||||||
|
println!("🚀 Escape Room Server active on port 5901");
|
||||||
|
println!("Waiting for teams to connect...");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (socket, _) = listener.accept().await?;
|
||||||
|
let db_clone = Arc::clone(&db);
|
||||||
|
|
||||||
|
// Spawn a new async task for every connection
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = handle_connection(socket, db_clone).await {
|
||||||
|
eprintln!("[SOCKET ERROR] {}", e);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_connection(mut socket: TcpStream, db: Db) -> std::io::Result<()> {
|
||||||
|
let mut buf = [0; 1024];
|
||||||
|
let n = socket.read(&mut buf).await?;
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = String::from_utf8_lossy(&buf[..n]);
|
||||||
|
let parts: Vec<&str> = request.trim().split_whitespace().collect();
|
||||||
|
|
||||||
|
if parts.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
match parts[0].to_uppercase().as_str() {
|
||||||
|
"PUT" => {
|
||||||
|
if parts.len() == 3 {
|
||||||
|
let team_id = parts[1].to_string();
|
||||||
|
let val_str = parts[2];
|
||||||
|
|
||||||
|
// Validate if the value is an integer
|
||||||
|
if val_str.parse::<i32>().is_ok() {
|
||||||
|
let mut data = db.write().await;
|
||||||
|
data.insert(team_id.clone(), val_str.to_string());
|
||||||
|
socket.write_all(b"ACK\n").await?;
|
||||||
|
println!("[LOG] Team {} submitted solution: {}", team_id, val_str);
|
||||||
|
} else {
|
||||||
|
// Send error but don't stop the server
|
||||||
|
socket.write_all(b"ERR_NOT_AN_INT\n").await?;
|
||||||
|
println!("[WARN] Team {} tried to send non-int: {}", team_id, val_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"GET" => {
|
||||||
|
if parts.len() == 2 {
|
||||||
|
let target_id = parts[1];
|
||||||
|
let data = db.read().await;
|
||||||
|
|
||||||
|
let response = data
|
||||||
|
.get(target_id)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| "-1".to_string());
|
||||||
|
|
||||||
|
socket.write_all(response.as_bytes()).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"ADMIN" => {
|
||||||
|
if parts.len() == 4 && parts[1].to_uppercase() == "SET" {
|
||||||
|
let team_id = parts[2].to_string();
|
||||||
|
let val_str = parts[3];
|
||||||
|
|
||||||
|
if val_str.parse::<i32>().is_ok() {
|
||||||
|
let mut data = db.write().await;
|
||||||
|
data.insert(team_id.clone(), val_str.to_string());
|
||||||
|
socket.write_all(b"ADMIN_OK\n").await?;
|
||||||
|
println!("[ADMIN] Manual set: Team {} -> {}", team_id, val_str);
|
||||||
|
} else {
|
||||||
|
socket.write_all(b"ADMIN_ERR_NOT_AN_INT\n").await?;
|
||||||
|
println!("[ADMIN] Manual set failed: {} is not an int", val_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
socket.write_all(b"ERR_INVALID_CMD\n").await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user