commit a1a5923f79ed8e3d438cb0cfcfd58689ad50d90b Author: Niklas Kapelle Date: Fri Feb 21 20:17:40 2025 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..f5b97ae --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,392 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "beerpong" +version = "0.1.0" +dependencies = [ + "chrono", + "regex", + "serde", + "serde_json", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb94a0ffd3f3ee755c20f7d8752f45cac88605a4dcf808abcff72873296ec7b" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "proc-macro2" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "wasm-bindgen" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef073ced962d62984fb38a36e5fdc1a2b23c9e0e1fa0689bb97afa4202ef6887" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4bfab14ef75323f4eb75fa52ee0a3fb59611977fd3240da19b2cf36ff85030e" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7bec9830f60924d9ceb3ef99d55c155be8afa76954edffbb5936ff4509474e7" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c74f6e152a76a2ad448e223b0fc0b6b5747649c3d769cc6bf45737bf97d0ed6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42f6c679374623f295a8623adfe63d9284091245c3504bde47c17a3ce2777d9" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7475e9a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "beerpong" +version = "0.1.0" +edition = "2021" + +[dependencies] +chrono = { version = "0.4.38", features = ["serde"] } +regex = "1.10.6" +serde = { version = "1.0.210", features = ["derive"]} +serde_json = "1.0.128" diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..9334e9f --- /dev/null +++ b/src/game.rs @@ -0,0 +1,23 @@ +use std::fmt::Display; +use chrono::{DateTime, FixedOffset, Local, Utc}; +use serde::{Serialize, Serializer}; + +#[derive(Serialize)] +pub struct Game{ + pub added: DateTime, + pub author: String, + pub t0p0: String, + pub t0p1: String, + pub t1p0: String, + pub t1p1: String, + pub score: i8, + pub ot: bool, +} + +impl Display for Game { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f,"{} {}: {} + {} ({}) {} + {} {}",self.added.to_string(),self.author,self.t0p0,self.t0p0,self.score,self.t1p0,self.t1p1,if self.ot { "(OT)" } else { ""}) + } +} + + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f12b64d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,10 @@ +mod game; +mod names; +mod raw_parser; + +fn main() { + let games = raw_parser::parse_file("./data/chat.txt").unwrap(); + let json = serde_json::to_string(&games).unwrap(); + + println!("{}",json); +} diff --git a/src/names.rs b/src/names.rs new file mode 100644 index 0000000..7ff081e --- /dev/null +++ b/src/names.rs @@ -0,0 +1,52 @@ +pub fn normalize_name(name: &str) -> Option { + let lower_name = name.to_lowercase(); + + let rtn = match lower_name.as_str(){ + "niklas" | "niklas kapelle" => "niklas", + "kilian" | "kili" => "kilian", + "luca" | "luca göttle" => "luca", + "line" | "line frische" => "line", + "simon" | "simon müller" => "simon", + "tim" | "tim waldherr" => "tim", + "manu" | "manuel kraiss" | "manuel"=> "manu", + "vivi" | "vivien" | "vivien (simon)" => "vivien", + "mika" | "mika wielsch" => "mika", + "kathi" => "kathi", + "guido" => "guido", + "tanita" => "tanita", + "elias" => "elias", + "moritz" | "moritz hübner" | "morirz" | "moritz huebner" => "moritz", + "liz" => "liz", + "adi" | "adrian" => "adi", + "fabi" => "fabi", + "bühl" | "felix" => "bühl", + "benni" | "benjamin passow" => "benni", + "maike" => "maike", + "aliern" => "aliern", + "jasmina" => "jasmina", + "alisa" | "alissa" => "alisa", + "linda" => "linda", + "judi" => "judi", + "hannah" => "hannah", + "elena" => "elena", + "sina" => "sina", + "mario" | "pablo" | "p4blo" | "mario lopez" => "mario", + "julian" => "julian", + "siggi" => "siggi", + "elisa" | "eli" | "elli" => "elisa", + "marvin" | "marvin göttle" => "marvin", + "aileen" | "eileen" => "aileen", + "murillo" => "murillo", + "will" => "will", + "muriel" => "muriel", + "leslie" => "leslie", + "ina" => "ina", + "kim" => "kim", + "naomi" => "naomi", + _=> { + return None; + } + }; + + Some(rtn.to_string()) +} diff --git a/src/raw_parser.rs b/src/raw_parser.rs new file mode 100644 index 0000000..5cbe71b --- /dev/null +++ b/src/raw_parser.rs @@ -0,0 +1,67 @@ +use std::{error::Error, fs::read_to_string}; +use chrono::{FixedOffset, NaiveDateTime, TimeZone}; +use regex::Regex; +use crate::game::Game; + +use super::names::normalize_name; + +pub fn parse_file(file: &str) -> Result, Box> { + let file = read_to_string(file)?; + let games = file.lines().map(parse_line); + + games.clone().for_each(|e| { + if let Err(err) = e { eprintln!("{}",err) } + }); + + Ok(games.flatten().collect()) +} + +fn parse_line(line: &str) -> Result>{ + let regex = Regex::new(r"(?m)^(\d+/\d+/\d+, \d+:\d+) - (.*): (.*)\+(.*) (\d)\s*[-:]\s*(\d) (.*)\+(.*?)(\s*\(?OT\)?)?\s*$")?; + + let Some(caps) = regex.captures(line) else { + return Err(format!("Failed to match regex: {}",line).into()); + }; + + let capture_groups: Vec = caps + .iter() + .skip(1) + .flatten() + .map(|cap| cap.as_str().to_string()) + .collect(); + + let date_time = NaiveDateTime::parse_from_str(capture_groups.first().unwrap().trim(), "%m/%d/%y, %H:%M")?; + let fixed_offset = FixedOffset::east_opt(2 * 3600).expect("Invalid timezone offset"); + + + let author = capture_groups.get(1).unwrap().trim(); + + let t1_0 = capture_groups.get(2).unwrap().trim(); + let t1_1 = capture_groups.get(3).unwrap().trim(); + + let cups_t1: i8 = capture_groups.get(4).unwrap().parse()?; + let cups_t2: i8 = capture_groups.get(5).unwrap().parse()?; + + let t2_0 = capture_groups.get(6).unwrap().trim(); + let t2_1 = capture_groups.get(7).unwrap().trim(); + + let is_ot = capture_groups.get(8).is_some(); + + let norm_t1_0 = normalize_name(t1_0).ok_or_else(|| format!("Unknown name: {} on line {}",t1_0,line))?; + let norm_t1_1 = normalize_name(t1_1).ok_or_else(|| format!("Unknown name: {} on line {}",t1_1,line))?; + let norm_t2_0 = normalize_name(t2_0).ok_or_else(|| format!("Unknown name: {} on line {}",t2_0,line))?; + let norm_t2_1 = normalize_name(t2_1).ok_or_else(|| format!("Unknown name: {} on line {}",t2_1,line))?; + let norm_author = normalize_name(author).unwrap_or_else(|| "unknown".to_string()); + + Ok(Game{ + added: fixed_offset.from_utc_datetime(&date_time), + author: norm_author, + t0p0: norm_t1_0, + t0p1: norm_t1_1, + t1p0: norm_t2_0, + t1p1: norm_t2_1, + score: cups_t1 - cups_t2, + ot: is_ot, + }) +} +