commit dbd679fa2a7e82c27da26eafd3a266c9171a8482 Author: Erin Power Date: Tue May 26 22:00:12 2015 +0100 First draft of Rusty CLOC diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..606a548 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,34 @@ +[root] +name = "rusty-cloc" +version = "0.1.0" +dependencies = [ + "getopts 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getopts" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..37c417f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rusty-cloc" +version = "0.1.0" +authors = ["Aaronepower "] + +[dependencies] +getopts = "0.2" +glob = "*" + +[profile.dev] +debug = true + + +[profile.release] +opt-level = 3 \ No newline at end of file diff --git a/src/language.rs b/src/language.rs new file mode 100644 index 0000000..3606872 --- /dev/null +++ b/src/language.rs @@ -0,0 +1,52 @@ +use std::fmt; + +pub struct Language<'a> { + pub name: &'a str, + pub line_comment: &'a str, + pub multi_line: &'a str, + pub multi_line_end: &'a str, + pub files: Vec, + pub code: u32, + pub comments: u32, + pub blanks: u32, + pub lines: u32, + pub total: usize, +} + +impl<'a> Language<'a> { + pub fn new<'b>(name: &'a str, + line_comment: &'a str, + multi_line: &'a str, + multi_line_end: &'a str) -> Language<'a> { + + Language { + name: name, + line_comment: line_comment, + multi_line: multi_line, + multi_line_end: multi_line_end, + files: Vec::new(), + code: 0, + comments: 0, + blanks: 0, + lines: 0, + total: 0, + } + } + + pub fn is_empty(&self) -> bool { + self.code == 0 && self.comments == 0 && self.blanks == 0 && self.lines == 0 + } +} + +impl<'a> fmt::Display for Language<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut total; + + if self.total == 0 { + total = self.files.len() + } else { + total = self.total; + } + write!(f," {: <15} {: >15} {:>15} {:>15} {:>15} {:>15} ", self.name, total, self.lines, self.blanks, self.comments, self.code) + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..998aee1 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,183 @@ +extern crate getopts; +extern crate glob; + +pub mod language; + +use std::env; +use std::fs; +use std::io::Read; +use std::path::Path; +use std::fs::{File, metadata}; +use std::collections::HashMap; +use self::glob::glob; +use getopts::Options; +use language::Language; + +fn main() { + let args: Vec = env::args().collect(); + let mut opts = Options::new(); + + opts.optflag("h", "help", "Print this help menu"); + opts.optopt("", "exclude-dir", "Example: --exclude-dir=docs", "\tDirectories wanted to be ignored"); + + let matches = opts.parse(&args[1..]).unwrap(); + let mut ignored_directories: Vec = Vec::new(); + ignored_directories.push(".git".to_string()); + + if matches.opt_present("h") { + let brief = format!("Usage: {} [options] [paths]", args[0].clone()); + println!("{}", opts.usage(&brief)); + return; + } + + if matches.opt_present("exclude-dir") { + let exclude_args = matches.opt_str("exclude-dir").unwrap(); + let exclude_vec = exclude_args.split(","); + + + for excluded in exclude_vec { + ignored_directories.push(excluded.to_string()); + } + } + + if !matches.free.is_empty() { + println!("----------------------------------------------------------------------------------------------------"); + println!(" {:<15} {:>15} {:>15} {:>15} {:>15} {:>15} ", + "language", "files", "total", "blanks", "comments", "code"); + println!("----------------------------------------------------------------------------------------------------"); + let mut languages: HashMap<&str, Language> = HashMap::new(); + languages.insert("cpp" , Language::new("C++", "//","/*","*/")); + languages.insert("hpp" , Language::new("C++ Header", "//","/*","*/")); + languages.insert("c" , Language::new("C", "//","/*","*/")); + languages.insert("h" , Language::new("C Header", "//","/*","*/")); + languages.insert("css" , Language::new("CSS", "//","/*","*/")); + languages.insert("java" , Language::new("Java", "//","/*","*/")); + languages.insert("js" , Language::new("JavaScript", "//","/*","*/")); + languages.insert("rs" , Language::new("Rust", "//","/*","*/")); + languages.insert("xml" , Language::new("XML", "")); + languages.insert("html" , Language::new("HTML", "")); + languages.insert("py" , Language::new("Python", "#","'''","'''")); + languages.insert("rb" , Language::new("Ruby", "#","=begin","=end")); + + for path in matches.free { + let files = get_all_files(path, &ignored_directories); + + for file in files { + let extension = match Path::new(&file).extension() { + Some(result) => result.to_str().unwrap(), + None => continue, + }; + + let mut language = match languages.get_mut(extension) { + Some(result) => result, + None => continue, + }; + language.files.push(file.to_string()); + } + } + + let mut total = Language::new("Total", "", "", ""); + + for (_, language) in languages.iter_mut() { + + for file in language.files.iter() { + let mut buffer: Vec = Vec::new(); + + let mut file_ref = match File::open(&file) { + Ok(result) => result, + _ => continue, + }; + + let _ = file_ref.read_to_end(&mut buffer); + + let contents = match String::from_utf8(buffer) { + Ok(result) => result, + Err(_) => continue, + }; + + let mut is_in_comments = false; + + for line in contents.lines() { + let line = line.trim(); + language.lines += 1; + + if line.starts_with(language.multi_line) { + language.comments += 1; + is_in_comments = true; + } else if line.contains(language.multi_line) { + language.code += 1; + is_in_comments = true; + } + + if is_in_comments { + if line.contains(language.multi_line_end) { + is_in_comments = false; + } + language.comments += 1; + continue; + } + + if line.starts_with(language.line_comment) { + language.comments += 1; + } else if line.trim().is_empty() { + language.blanks += 1; + } else { + language.code += 1; + } + }; + } + if !language.is_empty() { + println!("{}", language); + } + total.total += language.files.len(); + total.lines += language.lines; + total.comments += language.comments; + total.blanks += language.blanks; + total.code += language.code; + } + println!("----------------------------------------------------------------------------------------------------"); + println!("{}", total); + println!("----------------------------------------------------------------------------------------------------"); + } +} + + + +fn get_all_files(path: String, ignored_directories: &Vec) -> Vec { + let mut files: Vec = Vec::new(); + + if let Ok(result) = metadata(&path) { + if result.is_dir() { + let dir = fs::read_dir(&path).unwrap(); + 'file: for entry in dir { + let dir_entry = entry.unwrap(); + let file_path = dir_entry.path(); + let file_str = file_path.to_str().unwrap(); + let file_string = file_str.to_string(); + let path_metadata = metadata(&file_string).unwrap(); + + if path_metadata.is_dir() { + for ignored_directory in ignored_directories { + if file_str.contains(ignored_directory) { + continue 'file; + } + } + for file in get_all_files(file_string, &ignored_directories) { + files.push(file); + } + } else if path_metadata.is_file() { + files.push(file_string); + } + } + } else { + files.push(path); + } + } else { + for path_buf in glob(&path).unwrap() { + let file_path = path_buf.unwrap().as_path().to_str().unwrap().to_string(); + files.push(file_path); + } + } + + files +} \ No newline at end of file diff --git a/src/test/Another document.txt b/src/test/Another document.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/test/Cmder.exe b/src/test/Cmder.exe new file mode 100644 index 0000000..f5cab6d Binary files /dev/null and b/src/test/Cmder.exe differ diff --git a/src/test/JavaScript/APIService.js b/src/test/JavaScript/APIService.js new file mode 100644 index 0000000..b2bf542 --- /dev/null +++ b/src/test/JavaScript/APIService.js @@ -0,0 +1,35 @@ +function APIService ($http, $resource, TokenService) { + + var usersRoute = '/api/users/' + + var User = $resource( usersRoute + , {} + , { signin : { method : 'POST' + , url : usersRoute+'signin' + } + + , update : { method : 'PUT' + } + + , add : { method: 'POST' + , url : usersRoute+'add' + } + + , accept : { method: 'POST' + , url : usersRoute+'accept' + } + + , remove : { method : 'POST' + , url : usersRoute+'remove' + } + + , validate : { method : 'GET' + , url : usersRoute+'validate' + } + } + ) + return User +} + +angular.module('Echo') + .factory('API', APIService) diff --git a/src/test/JavaScript/CallService.js b/src/test/JavaScript/CallService.js new file mode 100644 index 0000000..ef2c92d --- /dev/null +++ b/src/test/JavaScript/CallService.js @@ -0,0 +1,55 @@ +function CallService (UserService) { + var webrtc + + function startCall(ID) { + webrtc = new SimpleWebRTC({ + localVideoEl: 'local', + remoteVideosEl: 'remotes', + autoRequestMedia: true + }) + + webrtc.on('readyToCall', function () { + webrtc.joinRoom(ID) + }) + } + + function endCall() { + webrtc.disconnect() + } + + function sendOffer() { + console.log(UserService.getUser()) + console.log(UserService.getUserID()) + socket.emit('callOffer', UserService.getUserID(), UserService.getFriend()) + + socket.on('callAccepted', function (receiverID) { + startCall(receiverID) + }) + + socket.on('callRejected', function (receiverID) { + // TODO Replace in the UI + alert('User is busy,') + }) + } + + socket.on('callOffer', function (senderID) { + console.log('Call Offered from: '+senderID) + // TODO Replace within the UI + var callConfirm = confirm(senderID+' is calling you. Accept?') + + if (callConfirm) { + socket.emit('callAccepted', senderID, UserService.getUserID()) + startCall(UserService.getUserID()) + } + else { + socket.emit('callRejected', senderID, UserService.getID()) + } + }) + + return { sendOffer : sendOffer + , endCall : endCall + } +} + +angular.module('Echo') +.factory('CallService', CallService) diff --git a/src/test/JavaScript/TokenService.js b/src/test/JavaScript/TokenService.js new file mode 100644 index 0000000..e2f7a12 --- /dev/null +++ b/src/test/JavaScript/TokenService.js @@ -0,0 +1,27 @@ +function TokenService ($window) { + var tokenKey = 'Token' + function getToken () { + return $window.localStorage.getItem(tokenKey) + } + + function setToken (token) { + $window.localStorage.setItem(tokenKey, token) + console.log('Token set: ', token) + tokenService.token = getToken() + } + + function tokenExists () { + return getToken() !== null + } + + var tokenService = { getToken : getToken + , setToken : setToken + , tokenExists : tokenExists + , token : getToken() + } + + return tokenService +} + +angular.module('Echo') + .factory('TokenService', TokenService) diff --git a/src/test/JavaScript/UserService.js b/src/test/JavaScript/UserService.js new file mode 100644 index 0000000..402f8cd --- /dev/null +++ b/src/test/JavaScript/UserService.js @@ -0,0 +1,60 @@ +function UserService ($location, jwtHelper, TokenService) { + var user + , friendID = '' + + function createUser (token) { + user = jwtHelper.decodeToken(token) + var event = new CustomEvent('userCreated', {detail : user}) + document.dispatchEvent(event) + } + + function getUser () { + return user + } + + function getUserID () { + return user._id + } + + function setFriend(newFriendID) { + friendID = newFriendID + } + + function getFriend () { + return friendID + } + + function loginEvent (token) { + createUser(token) + TokenService.setToken(token) + socket.emit('logged-in', getUserID()) + } + /* + Hi + + This should be 5 + + Thanks + */ + function loginSuccess(response) { + loginEvent(response.token) + $location.path('/dashboard') + } + + function loginError (response) { + // TODO show errors to user + console.log(response.status) + } + return { createUser : createUser + , loginSuccess : loginSuccess + , loginError : loginError + , loginEvent : loginEvent + , getUser : getUser + , getUserID : getUserID + , setFriend : setFriend + , getFriend : getFriend + } +} + +angular.module('Echo') + .factory('UserService', UserService) diff --git a/src/test/Rust/main.rs b/src/test/Rust/main.rs new file mode 100644 index 0000000..f6db0f3 --- /dev/null +++ b/src/test/Rust/main.rs @@ -0,0 +1,66 @@ +use std::thread; + +use std::sync::{Mutex, Arc}; + +struct Table { + forks: Vec>, +} + +struct Philosopher { + name: String, + left: usize, + right: usize, +} + +impl Philosopher { + fn new(name: &str, left: usize, right: usize) -> Philosopher { + Philosopher { + name: name.to_string(), + left: left, + right: right, + } + } + + fn eat(&self, table: &Table) { /* + This should be 2 + */ + + let _left = table.forks[self.left].lock().unwrap(); + let _right = table.forks[self.right].lock().unwrap(); + println!("{} is eating.", self.name); + + thread::sleep_ms(1000); + + println!("{} is done eating.", self.name); + } +} + +fn main() { + + let table = Arc::new(Table { forks: vec![ + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + ]}); + + let philosophers = vec![ + Philosopher::new("Baruch Spinoza", 0, 1), + Philosopher::new("Gilles Deleuze", 1, 2), + Philosopher::new("Karl Marx", 2, 3), + Philosopher::new("Friedrich Nietzsche", 3, 4), + Philosopher::new("Michel Foucault", 0, 4), + ]; + + let handles: Vec<_> = philosophers.into_iter().map(|p| { + let table = table.clone(); + thread::spawn(move || { + p.eat(&table); + }) + }).collect(); + + for h in handles { + h.join().unwrap(); + } +} \ No newline at end of file diff --git a/src/test/Test document.txt b/src/test/Test document.txt new file mode 100644 index 0000000..29c62ca --- /dev/null +++ b/src/test/Test document.txt @@ -0,0 +1,44 @@ + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec lacus vitae augue rhoncus +commodo eu vitae enim. Donec dignissim orci efficitur pellentesque consequat. Nam risus odio, +euismod nec aliquam ut, sollicitudin at orci. Curabitur volutpat porttitor nisl quis venenatis. + Mauris et urna massa. In eu gravida magna. Nunc rutrum tincidunt nisl, eget ullamcorper ipsum +consectetur suscipit. Ut non turpis in risus tempor hendrerit sed at leo. In ut lectus a felis +tempor egestas eu at purus. Integer volutpat nec est sed convallis. Nulla mollis odio vitae nisi + semper hendrerit. Donec vestibulum urna sed porta lacinia. Vestibulum vehicula nulla vel orci +posuere condimentum. Donec at ligula viverra, ornare augue at, commodo risus. + +Pellentesque eu euismod nisl. Duis non neque cursus erat condimentum facilisis quis sed ante. In +fringilla augue sit amet eros imperdiet, in tincidunt lectus tincidunt. In cursus condimentum +blandit. Quisque rutrum elit nec est euismod ultricies. Nam elementum nibh dignissim dapibus +convallis. Donec et faucibus ipsum. Ut egestas, ante vitae gravida commodo, massa neque commodo +nisi, in convallis turpis sapien sagittis sapien. Etiam cursus urna in risus feugiat malesuada. + Pellentesque vitae ligula et nunc luctus pretium quis quis sem. Sed lobortis facilisis nisl, nec + cursus arcu porttitor ac. Curabitur tincidunt facilisis tortor, ut mollis nibh scelerisque in. +Aenean in justo at quam bibendum hendrerit eu quis eros. + + + +Aenean et purus ut ipsum ultrices tempus. Integer hendrerit quis sem eu tempor. Mauris condimentum +nisi eu lobortis hendrerit. Curabitur et pretium odio. Vestibulum hendrerit ipsum consectetur, +commodo ante eget, interdum nibh. Donec ullamcorper nunc ac massa laoreet tristique. Morbi quis +pharetra ligula. Duis ornare in sapien vulputate fermentum. Vivamus non hendrerit nunc. + + +Nulla sit amet nibh justo. Aliquam turpis lectus, venenatis quis nibh sit amet, semper imperdiet + metus. Etiam a ante metus. Nam egestas ut velit sit amet bibendum. Phasellus sollicitudin sodales + diam, a finibus nisl vestibulum eu. Proin eget felis enim. Praesent luctus ut velit imperdiet +pharetra. Etiam laoreet libero et lorem iaculis, bibendum mollis lorem lobortis. Integer lobortis +tristique arcu non ultrices. + + +Praesent cursus lorem a erat consequat, eget efficitur erat viverra. Ut dignissim nunc vitae dolor + cursus, a sodales nunc fermentum. Ut nec euismod sapien, vitae dignissim augue. Morbi est erat, +consequat non ornare eu, molestie non urna. Vestibulum sit amet metus non ligula ultricies sodales + ut et tortor. Praesent congue auctor erat, ac scelerisque nibh ultrices at. Pellentesque euismod +odio ac massa pulvinar consequat vel eget neque. Nunc ut felis id dui consequat hendrerit. Nulla +volutpat ultrices mauris eu aliquam. Nullam sit amet tortor gravida quam fringilla tempor. Aenean +vitae odio elementum, blandit odio quis, convallis odio. Pellentesque habitant morbi tristique +senectus et netus et malesuada fames ac turpis egestas. Nunc gravida vel mi in gravida. +Pellentesque libero sem, tincidunt nec tellus eu, consectetur sollicitudin nunc. diff --git a/src/test/cpp/cppkoans.cpp b/src/test/cpp/cppkoans.cpp new file mode 100644 index 0000000..a854038 --- /dev/null +++ b/src/test/cpp/cppkoans.cpp @@ -0,0 +1,77 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include "headers/koan_handler.hpp" +#include "headers/all_koans.hpp" + +using namespace std; + +/** + * + */ +int main() +{ + KoanHandler status; + + // Koan 00: getting started + Koan00_get_started koan00 = Koan00_get_started( &status ); + + // Koan 01: number types + Koan01_number_types koan01 = Koan01_number_types( &status ); + + // Koan 02: character types + Koan02_character_types koan02 = Koan02_character_types( &status ); + + // Koan 03: further types + Koan03_further_types koan03 = Koan03_further_types( &status ); + + // Koan 04: arrays + Koan04_arrays koan04 = Koan04_arrays( &status ); + + // Koan 05: pointers + Koan05_pointers koan05 = Koan05_pointers( &status ); + + // Koan XX: sample koans +// KoanXX_sample_koans koanXX = KoanXX_sample_koans( &status ); + + // Welcome message + status.start(); + + // The Path of Enlightment + koan00.run(); + koan01.run(); + koan02.run(); + koan03.run(); + koan04.run(); + koan05.run(); +// koanXX.run(); + + // Done. + status.end(); + return( 0 ); +} + +// EOF diff --git a/src/test/cpp/header/all_koans.hpp b/src/test/cpp/header/all_koans.hpp new file mode 100644 index 0000000..8d80d37 --- /dev/null +++ b/src/test/cpp/header/all_koans.hpp @@ -0,0 +1,35 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "koan00_get_started.hpp" +#include "koan01_number_types.hpp" +#include "koan02_character_types.hpp" +#include "koan03_further_types.hpp" +#include "koan04_arrays.hpp" +#include "koan05_pointers.hpp" +// When an episode of koans is added, it must be appended here +// #include "koanXX_sample_koans.hpp" + +// EOF diff --git a/src/test/cpp/header/fill_me_in_exception.hpp b/src/test/cpp/header/fill_me_in_exception.hpp new file mode 100644 index 0000000..17d24a8 --- /dev/null +++ b/src/test/cpp/header/fill_me_in_exception.hpp @@ -0,0 +1,66 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef FILL_ME_IN_HPP +#define FILL_ME_IN_HPP + +#include +#include + +class FillMeInException +{ + public: + std::string file; + int line; + std::string msg; + std::string expect; + FillMeInException( const std::string f, const int l, std::string s ) : file( f ), line( l ), msg( s ) { + file = file.substr( file.find_last_of( "/" ) + 1 ); + } + FillMeInException( const std::string f, const int l, std::string s, std::string e ) : file( f ), line( l ), msg( s ), expect( e ) { + file = file.substr( file.find_last_of( "/" ) + 1 ); + } + ~FillMeInException() {} +}; + +#define ASSERT_MSG(expr, msg) do { \ + if (!(expr)) \ + { \ + throw FillMeInException(__FILE__, __LINE__, msg); \ + }; \ + } while(0) + +#define ASSERT(expr) ASSERT_MSG(expr, "") +#define ASSERT_EQUAL(a, b) ASSERT_EQUAL_MSG(a, b, "") +#define ASSERT_EQUAL_MSG(a, b, msg) do { \ + if (!(a == b)) \ + { \ + std::ostringstream expect;\ + expect << a;\ + throw FillMeInException(__FILE__, __LINE__, msg, expect.str()); \ + }; \ + } while(0) + +#endif diff --git a/src/test/cpp/header/koan.hpp b/src/test/cpp/header/koan.hpp new file mode 100644 index 0000000..7353403 --- /dev/null +++ b/src/test/cpp/header/koan.hpp @@ -0,0 +1,40 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef KOAN_HPP +#define KOAN_HPP + +#include + +using namespace std; + +/** + * + */ +class Koan {}; + +#endif // KOAN_HPP + +// EOF diff --git a/src/test/cpp/header/koan00_get_started.hpp b/src/test/cpp/header/koan00_get_started.hpp new file mode 100644 index 0000000..5428504 --- /dev/null +++ b/src/test/cpp/header/koan00_get_started.hpp @@ -0,0 +1,71 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN00_GET_STARTED_HPP +#define KOAN00_GET_STARTED_HPP + +using namespace std; + +/** + * + */ +class Koan00_get_started : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 1; //! + + public: + /** + * + */ + Koan00_get_started( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan00_get_started() {} + + /** + * + */ + void run() { + status->episode_start( "first" ); + + status->eval_koan( *this, static_cast( &Koan00_get_started::cpp_is_not_too_hard ) ); + + status->episode_done( "first" ); + } + + private: + void cpp_is_not_too_hard(); +}; + +#endif // KOAN00_GET_STARTED_HPP + +// EOF diff --git a/src/test/cpp/header/koan01_number_types.hpp b/src/test/cpp/header/koan01_number_types.hpp new file mode 100644 index 0000000..ca4bfe5 --- /dev/null +++ b/src/test/cpp/header/koan01_number_types.hpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN01_NUMBER_TYPES_HPP +#define KOAN01_NUMBER_TYPES_HPP + +/** + * + */ +class Koan01_number_types : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 8; //! + + public: + /** + * + */ + Koan01_number_types( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan01_number_types() {} + + /** + * + */ + void run() { + status->episode_start( "second" ); + + status->eval_koan( *this, static_cast( &Koan01_number_types::simple_integer_numbers ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::integers_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::integers_can_be_negative ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::simple_floats ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::floats_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::going_double_precision ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::doubles_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::size_of_biggest_number ) ); + + status->episode_done( "second" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void simple_integer_numbers(); + void integers_have_a_size(); + void integers_can_be_negative(); + void simple_floats(); + void floats_have_a_size(); + void going_double_precision(); + void doubles_have_a_size(); + void size_of_biggest_number(); +}; + +#endif // KOAN01_NUMBER_TYPES_HPP + +// EOF diff --git a/src/test/cpp/header/koan02_character_types.hpp b/src/test/cpp/header/koan02_character_types.hpp new file mode 100644 index 0000000..e319501 --- /dev/null +++ b/src/test/cpp/header/koan02_character_types.hpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN02_CHARACTER_TYPES_HPP +#define KOAN02_CHARACTER_TYPES_HPP + +class Koan02_character_types : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 4; //! + + public: + /** + * + */ + Koan02_character_types( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan02_character_types() {} + + /** + * + */ + void run() { + status->episode_start( "third" ); + + status->eval_koan( *this, static_cast( &Koan02_character_types::lonely_characters ) ); + status->eval_koan( *this, static_cast( &Koan02_character_types::chars_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan02_character_types::chars_are_numbers ) ); + status->eval_koan( *this, static_cast( &Koan02_character_types::more_characters_are_strings ) ); + + status->episode_done( "third" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void lonely_characters(); + void chars_have_a_size(); + void chars_are_numbers(); + void more_characters_are_strings(); +}; + +#endif // KOAN02_CHARACTER_TYPES_HPP + +// EOF diff --git a/src/test/cpp/header/koan03_further_types.hpp b/src/test/cpp/header/koan03_further_types.hpp new file mode 100644 index 0000000..f04ed8b --- /dev/null +++ b/src/test/cpp/header/koan03_further_types.hpp @@ -0,0 +1,75 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN03_FURTHER_TYPES_HPP +#define KOAN03_FURTHER_TYPES_HPP + +class Koan03_further_types : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 1; //! + + public: + /** + * + */ + Koan03_further_types( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan03_further_types() {} + + /** + * + */ + void run() { + status->episode_start( "fourth" ); + + status->eval_koan( *this, static_cast( &Koan03_further_types::the_truth_has_a_name ) ); + + status->episode_done( "fourth" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void the_truth_has_a_name(); +}; + + +#endif // KOAN03_FURTHER_TYPES_HPP + +// EOF diff --git a/src/test/cpp/header/koan04_arrays.hpp b/src/test/cpp/header/koan04_arrays.hpp new file mode 100644 index 0000000..39c1364 --- /dev/null +++ b/src/test/cpp/header/koan04_arrays.hpp @@ -0,0 +1,76 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN04_ARRAYS_HPP +#define KOAN04_ARRAYS_HPP + +class Koan04_arrays : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 2; //! + + public: + /** + * + */ + Koan04_arrays( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan04_arrays() {} + + /** + * + */ + void run() { + status->episode_start( "fifth" ); + + status->eval_koan( *this, static_cast( &Koan04_arrays::listing_things ) ); + status->eval_koan( *this, static_cast( &Koan04_arrays::arrays_are_rigid ) ); + + status->episode_done( "fifth" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void listing_things(); + void arrays_are_rigid(); +}; + +#endif // KOAN04_ARRAYS_HPP + +// EOF diff --git a/src/test/cpp/header/koan05_pointers.hpp b/src/test/cpp/header/koan05_pointers.hpp new file mode 100644 index 0000000..360ed52 --- /dev/null +++ b/src/test/cpp/header/koan05_pointers.hpp @@ -0,0 +1,81 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN05_POINTERS_HPP +#define KOAN05_POINTERS_HPP + +// Rename the Episode +class Koan05_pointers : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 4; //! + + public: + /** + * + */ + Koan05_pointers( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan05_pointers() {} + + /** + * + */ + void run() { + status->episode_start( "sixth" ); + + status->eval_koan( *this, static_cast( &Koan05_pointers::they_are_just_variables ) ); + status->eval_koan( *this, static_cast( &Koan05_pointers::they_are_really_just_variables ) ); + status->eval_koan( *this, static_cast( &Koan05_pointers::they_have_power ) ); + status->eval_koan( *this, static_cast( &Koan05_pointers::they_are_not_almighty ) ); + + status->episode_done( "sixth" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void they_are_just_variables(); + void they_are_really_just_variables(); + void they_have_power(); + void they_are_not_almighty(); +}; + +#endif // KOAN05_POINTERS_HPP + +// EOF diff --git a/src/test/cpp/header/koanXX_sample_koans.hpp b/src/test/cpp/header/koanXX_sample_koans.hpp new file mode 100644 index 0000000..3ffc591 --- /dev/null +++ b/src/test/cpp/header/koanXX_sample_koans.hpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +// Do not to forget to rename the preprocessor directives as well! +#ifndef KOANXX_SAMPLE_KOANS_HPP +#define KOANXX_SAMPLE_KOANS_HPP + +// Rename the Episode +class KoanXX_sample_koans : Koan +{ + private: + KoanHandler *status; //! + // When ever a koan is added at the very bottom, this counter needs to be + // increased. + static const int num_tests = 1; //! + + public: + /** + * + */ + KoanXX_sample_koans( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~KoanXX_sample_koans() {} + + /** + * + */ + void run() { + // For each koan in this episode, one line needs to be written. + // The koans are executed in the order they are called here. + status->eval_koan( *this, static_cast( &KoanXX_sample_koans::a_sample_koan ) ); + + status->episode_done( "the-so-and-so'th" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // Add further Koans down here by defining their name. + // The implementation of these is done in ~/koans/koanXX_sample_koans.cpp + // REMARK: Do not forget to increase this.num_tests when you add another koan + void a_sample_koan(); +}; + +#endif // KOANXX_SAMPLE_KOANS_HPP + +// EOF diff --git a/src/test/cpp/header/koan_handler.cpp b/src/test/cpp/header/koan_handler.cpp new file mode 100644 index 0000000..adf4055 --- /dev/null +++ b/src/test/cpp/header/koan_handler.cpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + + +#include "koan_handler.hpp" + +using namespace std; + +KoanHandler::KoanHandler() : total_num_koans( 0 ), total_num_passed( 0 ) +{ +} + +void KoanHandler::eval_koan( Koan obj, void ( Koan::*koan )() ) +{ + try { + ( obj.*koan )(); + this->total_num_passed++; + } catch( FillMeInException ex ) { + this->print_failure( ex ); + exit( 1 ); + } +} + +void KoanHandler::register_koans( int num_koans ) +{ + this->total_num_koans += num_koans; +} + +void KoanHandler::start() +{ + cout << "*******************************************************************************" + << endl + << "**** Welcome to CppKoans ****" + << endl + << "**** The master has " << this->total_num_koans + << " koans for you. ****" + << endl << endl; +} + +void KoanHandler::end() +{ + cout << "**** You've walked the path to enlightment and satisfied your master. ****" + << endl + << "*******************************************************************************" + << endl; +} + +void KoanHandler::episode_start( string order ) +{ + cout << "****\tThe " << order << " episode." << endl; +} + +void KoanHandler::episode_done( string order ) +{ + cout << "****\tCongratulations! You mastered the " << order << " episode." << endl + << "****\tDon't loose concentration. Keep going!" << endl + << endl; +} + +void KoanHandler::print_failure( FillMeInException ex ) +{ + if( !ex.msg.empty() ) { + cout << "Note:\t" << ex.msg << endl; + } + cout << "The master says, that you should meditate on '" << ex.file << ":" + << ex.line << "'." + << endl; + if( !ex.expect.empty() ) { + cout << "The master expected " << ex.expect << "." << endl; + } + cout << endl + << "**** You mastered " << this->total_num_passed << " of " + << this->total_num_koans << " koans. ****" + << endl + << "**** Keep going! ****" + << endl; +} + +// EOF diff --git a/src/test/cpp/header/koan_handler.hpp b/src/test/cpp/header/koan_handler.hpp new file mode 100644 index 0000000..6907235 --- /dev/null +++ b/src/test/cpp/header/koan_handler.hpp @@ -0,0 +1,90 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef KOAN_HANDLER_HPP +#define KOAN_HANDLER_HPP + +#include +#include "fill_me_in_exception.hpp" +#include "koan.hpp" + +using namespace std; + +/** + * + */ +class KoanHandler +{ + private: + int total_num_koans; //! + int total_num_passed; //! + + public: + /** + * + */ + KoanHandler(); + + /** + * + */ + void eval_koan( Koan obj, void ( Koan::*koan )() ); + + /** + * + */ + void register_koans( int num_koans ); + + /** + * + */ + void start(); + + /** + * + */ + void end(); + + /** + * + */ + void episode_start( string order ); + + /** + * + */ + void episode_done( string order ); + + private: + /** + * + */ + void print_failure( FillMeInException ex ); +}; + +#endif // KOAN_HANDLER_HPP + +// EOF diff --git a/src/test/css/normalize.css b/src/test/css/normalize.css new file mode 100644 index 0000000..81c6f31 --- /dev/null +++ b/src/test/css/normalize.css @@ -0,0 +1,427 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} \ No newline at end of file diff --git a/src/test/css/skeleton.css b/src/test/css/skeleton.css new file mode 100644 index 0000000..f28bf6c --- /dev/null +++ b/src/test/css/skeleton.css @@ -0,0 +1,418 @@ +/* +* Skeleton V2.0.4 +* Copyright 2014, Dave Gamache +* www.getskeleton.com +* Free to use under the MIT license. +* http://www.opensource.org/licenses/mit-license.php +* 12/29/2014 +*/ + + +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #222; } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 2rem; + font-weight: 300; } +h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } +h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } +h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } +h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } + +/* Larger than phablet */ +@media (min-width: 550px) { + h1 { font-size: 5.0rem; } + h2 { font-size: 4.2rem; } + h3 { font-size: 3.6rem; } + h4 { font-size: 3.0rem; } + h5 { font-size: 2.4rem; } + h6 { font-size: 1.5rem; } +} + +p { + margin-top: 0; } + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; } +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; } +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: .5rem; + font-weight: 600; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Code +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +code { + padding: .2rem .5rem; + margin: 0 .2rem; + font-size: 90%; + white-space: nowrap; + background: #F1F1F1; + border: 1px solid #E1E1E1; + border-radius: 4px; } +pre > code { + display: block; + padding: 1rem 1.5rem; + white-space: pre; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 1rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 1.5rem; } +pre, +blockquote, +dl, +figure, +table, +p, +ul, +ol, +form { + margin-bottom: 2.5rem; } + + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} diff --git a/src/test/css/style.css b/src/test/css/style.css new file mode 100644 index 0000000..070ef71 --- /dev/null +++ b/src/test/css/style.css @@ -0,0 +1,201 @@ +html { + background-color: #0a0820; + font-size: 62.5%; + height: 100%; + width: 100%; +} + +@font-face { + font-family: "Signika"; + src: url(Signika-Regular.otf); +} +@font-face { + font-family: "League Gothic"; + src: url(LeagueGothic-Regular.otf); +} +body { + width: 100%; + height: 100%; +} + +.subheading { + text-align: center; +} + +.text, .secondheading, .subheading, #education { + color: white; +} + +.text { + font-size: 8rem; + font-family: "League Gothic"; +} + +.secondheading { + font-family: "Signika"; + font-size: 2rem; + opacity: .3; +} + +.subheading, #education { + font-family: "Signika"; + font-size: 3rem; + letter-spacing: 0.1rem; +} + +.body { + /*position: relative;*/ +} + +#education { + font-size: 2rem; + background-image: url(LowDefTelevision.jpg); +} + +.down-button { + margin: 0 39%; +} + +.work-container { + color: white; + display: inline-block; +} + +.work { + box-shadow: 10px 10px 5px black; + border-radius: 1rem; + background-color: #333; + display: inline-block; + padding: 1rem; + margin: 1rem; +} + +.work-title { + display: inline-block; + vertical-align: top; + padding-left: 5rem; + padding-top: 1.5rem; + margin-bottom: 0; +} + +.line-break { + margin: 1rem; + border-color: #d3d3d3; +} + +.legal { + position: absolute; + bottom: 0; + right: 0; + display: none; +} + +.work-header { + width: 100%; + text-align: center; +} + +.legal, .legal a { + color: #d3d3d3; +} + +video#bgvid { + position: fixed; + top: 50%; + left: 50%; + min-width: 100%; + min-height: 100%; + width: auto; + height: auto; + z-index: -100; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + background: url(LowDefTelevision.jpg) no-repeat; + background-size: cover; +} + +@media (max-width: 321px) { + .right-align { + padding-right: 2.5rem; + text-align: right; + } + + .work-header { + margin: 12.5%; + display: block; + } + + .work-header-title { + text-align: center; + } + + .work { + margin: 0.5rem; + } + + .left-align { + padding-left: 2.5rem; + } + .secondheading { + letter-spacing: .6rem; + } + + .down-button { + margin-bottom: 2.5rem; + } + + .work { + width: 90%; + } +} + +@media (min-width: 321px) and (max-width: 420px) { + .right-align { + padding-left: 15rem; + } + .left-align { + padding-left: 5rem; + } + .secondheading { + letter-spacing: .85rem; + } + + .down-button { + margin: 0 45%; + } + +} + +@media (max-width: 420px) { + .container { + padding: 0; + width: 75%; + margin: 20% 12%; + } + + .desktopTitle { + display: none; + } +} + +@media (min-width:421px) { + .mobile_title { + display: none; + } + + .desktopTitle { + font-size: 25rem; + text-align: center; + } + + .secondheading { + padding-left: 2rem; + font-size: 6rem; + letter-spacing: 3rem; + text-align: center; + } + + .down-button { + display: none; + } +} \ No newline at end of file diff --git a/src/test/java/StudentNetworkSimulator.java b/src/test/java/StudentNetworkSimulator.java new file mode 100644 index 0000000..7e24670 --- /dev/null +++ b/src/test/java/StudentNetworkSimulator.java @@ -0,0 +1,248 @@ + +public class StudentNetworkSimulator extends NetworkSimulator { + /* + * Predefined Constants (static member variables): + * + * int MAXDATASIZE : the maximum size of the Message data and + * Packet payload + * + * int A : a predefined integer that represents entity A + * int B : a predefined integer that represents entity B + * + * + * Predefined Member Methods: + * + * void stopTimer(int entity): + * Stops the timer running at "entity" [A or B] + * void startTimer(int entity, double increment): + * Starts a timer running at "entity" [A or B], which will expire in + * "increment" time units, causing the interrupt handler to be + * called. You should only call this with A. + * void toLayer3(int callingEntity, Packet p) + * Puts the packet "p" into the network from "callingEntity" [A or B] + * void toLayer5(int entity, String dataSent) + * Passes "dataSent" up to layer 5 from "entity" [A or B] + * double getTime() + * Returns the current time in the simulator. Might be useful for + * debugging. + * void printEventList() + * Prints the current event list to stdout. Might be useful for + * debugging, but probably not. + * + * + * Predefined Classes: + * + * Message: Used to encapsulate a message coming from layer 5 + * Constructor: + * Message(String inputData): + * creates a new Message containing "inputData" + * Methods: + * boolean setData(String inputData): + * sets an existing Message's data to "inputData" + * returns true on success, false otherwise + * String getData(): + * returns the data contained in the message + * Packet: Used to encapsulate a packet + * Constructors: + * Packet (Packet p): + * creates a new Packet that is a copy of "p" + * Packet (int seq, int ack, int check, String newPayload) + * creates a new Packet with a sequence field of "seq", an + * ack field of "ack", a checksum field of "check", and a + * payload of "newPayload" + * Packet (int seq, int ack, int check) + * chreate a new Packet with a sequence field of "seq", an + * ack field of "ack", a checksum field of "check", and + * an empty payload + * Methods: + * boolean setSeqnum(int n) + * sets the Packet's sequence field to "n" + * returns true on success, false otherwise + * boolean setAcknum(int n) + * sets the Packet's ack field to "n" + * returns true on success, false otherwise + * boolean setChecksum(int n) + * sets the Packet's checksum to "n" + * returns true on success, false otherwise + * boolean setPayload(String newPayload) + * sets the Packet's payload to "newPayload" + * returns true on success, false otherwise + * int getSeqnum() + * returns the contents of the Packet's sequence field + * int getAcknum() + * returns the contents of the Packet's ack field + * int getChecksum() + * returns the checksum of the Packet + * String getPayload() + * returns the Packet's payload + * + */ + + // Add any necessary class variables here. Remember, you cannot use + // these variables to send messages error free! They can only hold + // state information for A or B. + // Also add any necessary methods (e.g. checksum of a String) + + // 'A' VARIABLES + int aSeqNum; + int aAckNum; + boolean packetSent; + boolean newPacket; + Packet packet; + + private int createChecksum(Packet packet) { + return packet.getSeqnum() + + packet.getAcknum() + + packet.getPayload().hashCode(); + } + + // This is the constructor. Don't touch! + public StudentNetworkSimulator(int numMessages, + double loss, + double corrupt, + double avgDelay, + int trace, + long seed) { + super(numMessages, loss, corrupt, avgDelay, trace, seed); + } + + // This routine will be called whenever the upper layer at the sender [A] + // has a message to send. It is the job of your protocol to insure that + // the data in such a message is delivered in-order, and correctly, to + // the receiving upper layer. Return 1 if accepting the message to send, + // return 0 if refusing to send the message + @Override + protected int aOutput(Message message) { + // Only create a packet if no packet is in transit, + // and the last packet has been sent successfully. + if (!packetSent && newPacket) { + // Packet creation + packet = new Packet(aSeqNum, aAckNum, 0, message.getData()); + packet.setChecksum(createChecksum(packet)); + debug("SENDING PACKETS"); + toLayer3(A, packet); + startTimer(A, 1000); + debug("NEW PACKET"); + packetSent = true; + newPacket = false; + return packetSent && !newPacket ? 1 : 0; + } else { + toLayer3(A, packet); + return 0; + } + } + + // This routine will be called whenever a packet sent from the B-side + // (i.e. as a result of a toLayer3() being done by a B-side procedure) + // arrives at the A-side. "packet" is the (possibly corrupted) packet + // sent from the B-side. + @Override + protected void aInput(Packet packet) { + //***GETTING STARTED*** + // This will be needed later, when dealing with acknowledgments sent from B + if (packet.getChecksum() == createChecksum(packet)) { + + if (packet.getSeqnum() == aSeqNum) { + stopTimer(A); + aSeqNum = packet.getAcknum(); + aAckNum = packet.getSeqnum() + 1; + packetSent = false; + newPacket = true; + } else { + packetSent = false; + } + } else { + packetSent = false; + } + } + + // This routine will be called when A's timer expires (thus generating a + // timer interrupt). You'll probably want to use this routine to control + // the retransmission of packets. See startTimer() and stopTimer(), above, + // for how the timer is started and stopped. + @Override + protected void aTimerInterrupt() { + //***GETTING STARTED*** + // This will be needed later, to deal with lost packets + debug("PACKET DROPPED SENDING ANOTHER"); + toLayer3(A, packet); + packetSent = true; + startTimer(A, 1000); + } + + // This routine will be called once, before any of your other A-side + // routines are called. It can be used to do any required + // initialization (e.g. of member variables you add to control the state + // of entity A). + @Override + protected void aInit() { + //***GETTING STARTED*** + // This will be needed later + aSeqNum = 0; + aAckNum = 0; + newPacket = true; + } + + // 'B' variables + Packet lastPacket; + String debugString; + // This routine will be called whenever a packet sent from the A-side + // (i.e. as a result of a toLayer3() being done by an A-side procedure) + // arrives at the B-side. "packet" is the (possibly corrupted) packet + // sent from the A-side. + @Override + protected void bInput(Packet packet) { + //***GETTING STARTED*** + // To get started, extract the payload from the packet + // and then send it up toLayer5 + + // To see reliability search for LETTERS line in the output.. + // It takes the first letter of each packet and adds them to a string. + // Example 26 Packets: abcdefghijklmnopqrstuvwxyz || abcdefghijklmnopqrstuvwxy + // As the program begins to shutdown once the last packet has been received + // And if the packet is corrupted or + // dropped the program will end before it can be resent. + if (packet.getChecksum() == createChecksum(packet)) { + + Packet ack = new Packet(packet.getAcknum(), packet.getSeqnum() + 1, 0, "ack"); + ack.setChecksum(createChecksum(ack)); + debug("SENDING ACKS"); + toLayer3(B, ack); + if (lastPacket == null) { + + toLayer5(B, packet.getPayload()); + lastPacket = packet; + debug("LETTERS: " + (debugString += packet.getPayload().substring(0, 1))); + } else if (!packet.getPayload().equals(lastPacket.getPayload())) { + lastPacket = packet; + toLayer5(B, packet.getPayload()); + debug("LETTERS: " + (debugString += packet.getPayload().substring(0, 1))); + } + } else { + + Packet nack = new Packet(packet.getAcknum() - 1, packet.getSeqnum(), 0, "nack"); + nack.setChecksum(createChecksum(nack)); + toLayer3(B, nack); + debug("SENDING NACKS"); + } + } + + // This routine will be called once, before any of your other B-side + // routines are called. It can be used to do any required + // initialization (e.g. of member variables you add to control the state + // of entity B). + @Override + protected void bInit() { + //***GETTING STARTED*** + // This will be needed later + lastPacket = null; + debugString = ""; + } + + private void debug(String message) { + + System.out.println("************************************"); + System.out.println(message); + System.out.println("************************************"); + } +} diff --git a/src/test/python_script.py b/src/test/python_script.py new file mode 100644 index 0000000..f37c3e5 --- /dev/null +++ b/src/test/python_script.py @@ -0,0 +1,21 @@ +from snake import * + +@key_map("c") +def toggle_snake_case_camel_case(): + """ toggles a word between snake case (some_function) and camelcase + (someFunction) """ + word = get_word() + + # it's snake case + if "_" in word: + chunks = word.split("_") + camel_case = chunks[0] + "".join([chunk.capitalize() for chunk in + chunks[1:]]) + replace_word(camel_case) + + # it's camel case + else: + # split our word on capital letters followed by non-capital letters + chunks = filter(None, re.split("([A-Z][^A-Z]*)", word)) + snake_case = "_".join([chunk.lower() for chunk in chunks]) + replace_word(snake_case) \ No newline at end of file